Compare commits

..

31 Commits

Author SHA1 Message Date
Alex Lam S.L
75e2748b16 v2.8.27 2017-05-19 17:44:50 +08:00
Alex Lam S.L
a7c987ad2b Merge pull request #1971 from alexlamsl/v2.8.27 2017-05-19 17:21:39 +08:00
Alex Lam S.L
957c54bc87 introduce unsafe_regexp (#1970)
fixes #1964
2017-05-19 10:10:09 +08:00
Alex Lam S.L
4cbf5a7821 v2.8.26 2017-05-16 07:13:58 +08:00
Alex Lam S.L
93d4224072 Merge pull request #1947 from alexlamsl/v2.8.26 2017-05-16 07:12:28 +08:00
Alex Lam S.L
6cd580dc23 fix parsing of property access after new line (#1944)
Account for comments when detecting property access in `tokenizer`.

fixes #1943
2017-05-16 06:34:10 +08:00
Alex Lam S.L
ecb63ad8bc improve keyword-related parser errors (#1941)
fixes #1937
2017-05-16 06:33:57 +08:00
Alex Lam S.L
1ca43bcca1 v2.8.25 2017-05-15 19:45:33 +08:00
Alex Lam S.L
3ee1464aa4 Merge pull request #1938 from alexlamsl/v2.8.25 2017-05-15 19:44:44 +08:00
Alex Lam S.L
24967b8be8 fix & improve coverage of estree (#1935)
- fix `estree` conversion of getter/setter
- fix non-directive literal in `to_mozilla_ast()`
- revamp `test/mozilla-ast.js`
  - reuse `test/ufuzz.js` for code generation
  - use `acorn.parse()` for creating `estree`
- extend `test/ufuzz.js` for `acorn` workaround
  - catch variable redefinition
  - non-trivial literal as directive
  - adjust options for tolerance

Miscellaneous
- optional semi-colon when parsing directives

fixes #1914
closes #1915
2017-05-15 18:33:43 +08:00
Alex Lam S.L
a8c67ea353 fix bugs with getter/setter (#1926)
- `reduce_vars`
- `side_effects`
- property access for object
- `AST_SymbolAccessor` as key names

enhance `test/ufuzz.js`
- add object getter & setter
  - property assignment to setter
  - avoid infinite recursion in setter
- fix & adjust assignment operators
  - 50% `=`
  - 25% `+=`
  - 2.5% each for the rest
- avoid "Invalid array length"
- fix `console.log()`
  - bypass getter
  - curb recursive reference
- deprecate `-E`, always report runtime errors
2017-05-15 18:22:43 +08:00
olsonpm
d0b0aecfc5 document 3 max passes (#1928) 2017-05-15 18:18:38 +08:00
olsonpm
9f5a6029a3 clarify wording (#1931) 2017-05-15 18:18:27 +08:00
Alex Lam S.L
4027a0c962 fix parser bugs & CLI reporting (#1827)
fixes #1825
2017-05-15 18:18:04 +08:00
Alex Lam S.L
87f8a484e6 v2.8.24 2017-05-12 15:47:02 +08:00
Alex Lam S.L
c736834aa4 Merge pull request #1921 from alexlamsl/v2.8.24 2017-05-12 14:58:35 +08:00
olsonpm
9a98513981 add documentation for side_effects & [#@]__PURE__ (#1925) 2017-05-12 12:55:07 +08:00
Alex Lam S.L
f631d6437a avoid arguments and eval in reduce_vars (#1924)
fixes #1922
2017-05-12 12:45:38 +08:00
Alex Lam S.L
aa7e8783f8 fix invalid transform on const (#1919)
- preserve (re)assignment to `const` for runtime error
- suppress `cascade` on `const`, as runtime behaviour is ill-defined
2017-05-12 05:04:28 +08:00
Alex Lam S.L
13e5e33448 document known issues with const (#1916) 2017-05-12 03:36:54 +08:00
kzc
487ae8e3be change harmony references to uglify-es in README (#1902) 2017-05-10 16:38:10 +08:00
Alex Lam S.L
5dfda6e212 v2.8.23 2017-05-07 04:31:54 +08:00
Alex Lam S.L
d08c772eb3 Merge pull request #1871 from alexlamsl/v2.8.23 2017-05-07 04:06:51 +08:00
Alex Lam S.L
90ed54401b fix test for #1865 (#1873) 2017-05-07 03:04:17 +08:00
Alex Lam S.L
d8106b6c63 fix label-related bugs (#1835)
- deep cloning of `AST_LabeledStatement`
- `L:do{...}while(false)`
- empty statement with label within block

extend `test/ufuzz.js`
- generate labels for blocks & loops
- generate for-in statements
- skip suspicious option search if `minify()` errs

fixes #1833
2017-05-07 00:16:30 +08:00
alexlamsl
dda4eb96e1 backport test scripts 2017-05-06 23:48:28 +08:00
Alex Lam S.L
7305ba0296 fix unsafe on evaluate of reduce_vars (#1870)
Determine if variables with non-constant values can escape and be modified.

fixes #1865
2017-05-06 23:40:19 +08:00
Alex Lam S.L
2c21dc5e8e fix unused on for-in statements (#1843)
Only need to avoid `var` within the initialisation block.

fixes #1841
2017-05-06 23:34:21 +08:00
Alex Lam S.L
d0faa471db fix unused on labeled for-loop (#1831)
fixes #1830
2017-05-06 23:31:22 +08:00
Alex Lam S.L
6ad823d1e8 fix reduce_vars within try-block (#1818)
Possible partial execution due to exceptions.
2017-05-06 23:28:07 +08:00
Alex Lam S.L
43ad4e9775 fix variable substitution (#1816)
- let `collapse_vars` take care of value containing any symbols
- improve overhead accounting
2017-05-06 23:26:54 +08:00
216 changed files with 17400 additions and 66131 deletions

View File

@@ -1,25 +1,9 @@
**Bug report or feature request?** - Bug report or feature request? <!-- Note: sub-optimal but correct code is not a bug -->
- `uglify-js` version (`uglifyjs -V`)
<!-- Note: sub-optimal but correct code is not a bug --> - JavaScript input - ideally as small as possible.
- The `uglifyjs` CLI command executed or `minify()` options used.
**Uglify version (`uglifyjs -V`)** - An example of JavaScript output produced and/or the error or warning.
**JavaScript input**
<!-- <!--
A complete parsable JS program exhibiting the issue with Note: the release version of uglify-js only supports ES5. Those wishing
UglifyJS alone - without third party tools or libraries. to minify ES6 should use the experimental harmony branch.
Ideally the input should be as small as possible.
Post a link to a gist if necessary.
Issues without a reproducible test case will be closed.
-->
**The `uglifyjs` CLI command executed or `minify()` options used.**
**JavaScript output or error produced.**
<!--
Note: `uglify-js` only supports JavaScript.
Those wishing to minify ES6+ should transpile first.
--> -->

View File

@@ -1,45 +0,0 @@
name: CI
on: [ push, pull_request ]
jobs:
test:
strategy:
matrix:
node: [ "0.8", "0.10", "0.12", "4", "6", "8", "10", "12", latest ]
os: [ ubuntu-latest, windows-latest ]
script: [ compress, mocha, release/benchmark, release/jetstream ]
exclude:
- node: "0.8"
script: release/benchmark
- node: "0.8"
script: release/jetstream
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
runs-on: ${{ matrix.os }}
env:
NODE: ${{ matrix.node }}
TYPE: ${{ matrix.script }}
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v1
with:
path: tmp
key: tmp ${{ matrix.script }}
- name: Perform tests
shell: bash
run: |
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add $NODE && nvs use $NODE'; do
cd ~/.nvs
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done
cd -
done
. ~/.nvs/nvs.sh --version
nvs use $NODE
node --version
npm config set audit false
npm config set optional false
npm config set save false
npm config set strict-ssl false
npm config set update-notifier false
npm --version
while !(npm install); do echo "'npm install' failed - retrying..."; done
node test/$TYPE

View File

@@ -1,35 +0,0 @@
name: Fuzzing
on:
pull_request:
schedule:
- cron: "*/8 * * * *"
jobs:
ufuzz:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-latest, windows-latest ]
name: ${{ matrix.os }}
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Perform fuzzing
shell: bash
run: |
git clone --branch v1.5.4 --depth 1 https://github.com/jasongin/nvs.git ~/.nvs
while ! timeout 60 bash -c '. ~/.nvs/nvs.sh add 8 && nvs use 8'; do
cd ~/.nvs
while !(git clean -xdf); do echo "'git clean' failed - retrying..."; done
cd -
done
. ~/.nvs/nvs.sh --version
nvs use 8
node --version
npm config set audit false
npm config set optional false
npm config set save false
npm config set strict-ssl false
npm config set update-notifier false
npm --version
while !(npm install); do echo "'npm install' failed - retrying..."; done
node test/ufuzz/job 3600000

11
.travis.yml Normal file
View File

@@ -0,0 +1,11 @@
language: node_js
node_js:
- "0.10"
- "0.12"
- "4"
- "6"
env:
- UGLIFYJS_TEST_ALL=1
matrix:
fast_finish: true
sudo: false

View File

@@ -1,61 +0,0 @@
Contributing
============
## Documentation
Every new feature and API change should be accompanied by a README additon.
## Testing
All features and bugs should have tests that verify the fix. You can run all
tests using `npm test`.
The most common type of test are tests that verify input and output of the
Uglify transforms. These tests exist in `test/compress`. New tests can be added
either to an existing file or in a new file `issue-xxx.js`.
Tests that cannot be expressed as a simple AST can be found in `test/mocha`.
## Code style
- File encoding must be `UTF-8`.
- `LF` is always used as a line ending.
- Statements end with semicolons.
- Indentation uses 4 spaces, switch `case` 2 spaces.
- Identifiers use `snake_case`.
- Strings use double quotes (`"`).
- Use a trailing comma for multiline array and object literals to minimize diffs.
- The Uglify code only uses ES5, even in the `harmony` branch.
- Line length should be at most 80 cols, except when it is easier to read a
longer line.
- If both sides of a comparison are of the same type, `==` and `!=` are used.
- Multiline conditions place `&&` and `||` first on the line.
**Example feature**
```js
OPT(AST_Debugger, function(self, compressor) {
if (compressor.option("drop_debugger"))
return make_node(AST_EmptyStatement, self);
return self;
});
```
**Example test case**
```js
drop_debugger: {
options = {
drop_debugger: true,
}
input: {
debugger;
if (foo) debugger;
}
expect: {
if (foo);
}
}
```

View File

@@ -1,6 +1,6 @@
UglifyJS is released under the BSD license: UglifyJS is released under the BSD license:
Copyright 2012-2019 (c) Mihai Bazon <mihai.bazon@gmail.com> Copyright 2012-2013 (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

1660
README.md

File diff suppressed because it is too large Load Diff

24
appveyor.yml Normal file
View File

@@ -0,0 +1,24 @@
environment:
matrix:
- nodejs_version: "0.10"
- nodejs_version: "0.12"
- nodejs_version: "4.0"
- nodejs_version: "6.0"
matrix:
fast_finish: true
platform:
- x86
- x64
install:
- ps: Install-Product node $env:nodejs_version $env:platform
- npm install
test_script:
- node --version
- npm --version
- npm test
build: off

77
bin/extract-props.js Executable file
View File

@@ -0,0 +1,77 @@
#! /usr/bin/env node
"use strict";
var U2 = require("../tools/node");
var fs = require("fs");
var yargs = require("yargs");
var ARGS = yargs
.describe("o", "Output file")
.argv;
var files = ARGS._.slice();
var output = {
vars: {},
props: {}
};
if (ARGS.o) try {
output = JSON.parse(fs.readFileSync(ARGS.o, "utf8"));
} catch(ex) {}
files.forEach(getProps);
if (ARGS.o) {
fs.writeFileSync(ARGS.o, JSON.stringify(output, null, 2), "utf8");
} else {
console.log("%s", JSON.stringify(output, null, 2));
}
function getProps(filename) {
var code = fs.readFileSync(filename, "utf8");
var ast = U2.parse(code);
ast.walk(new U2.TreeWalker(function(node){
if (node instanceof U2.AST_ObjectKeyVal) {
add(node.key);
}
else if (node instanceof U2.AST_ObjectProperty) {
add(node.key.name);
}
else if (node instanceof U2.AST_Dot) {
add(node.property);
}
else if (node instanceof U2.AST_Sub) {
addStrings(node.property);
}
}));
function addStrings(node) {
var out = {};
try {
(function walk(node){
node.walk(new U2.TreeWalker(function(node){
if (node instanceof U2.AST_Seq) {
walk(node.cdr);
return true;
}
if (node instanceof U2.AST_String) {
add(node.value);
return true;
}
if (node instanceof U2.AST_Conditional) {
walk(node.consequent);
walk(node.alternative);
return true;
}
throw out;
}));
})(node);
} catch(ex) {
if (ex !== out) throw ex;
}
}
function add(name) {
output.props[name] = true;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,265 +0,0 @@
"use strict";
var to_ascii, to_base64;
if (typeof Buffer == "undefined") {
to_ascii = atob;
to_base64 = btoa;
} else if (typeof Buffer.alloc == "undefined") {
to_ascii = function(b64) {
return new Buffer(b64, "base64").toString();
};
to_base64 = function(str) {
return new Buffer(str).toString("base64");
};
} else {
to_ascii = function(b64) {
return Buffer.from(b64, "base64").toString();
};
to_base64 = function(str) {
return Buffer.from(str).toString("base64");
};
}
function read_source_map(name, toplevel) {
var comments = toplevel.end.comments_after;
for (var i = comments.length; --i >= 0;) {
var comment = comments[i];
if (comment.type != "comment1") break;
var match = /^# ([^\s=]+)=(\S+)\s*$/.exec(comment.value);
if (!match) break;
if (match[1] == "sourceMappingURL") {
match = /^data:application\/json(;.*?)?;base64,(\S+)$/.exec(match[2]);
if (!match) break;
return to_ascii(match[2]);
}
}
AST_Node.warn("inline source map not found: " + name);
}
function parse_source_map(content) {
try {
return JSON.parse(content);
} catch (ex) {
throw new Error("invalid input source map: " + content);
}
}
function set_shorthand(name, options, keys) {
if (options[name]) {
keys.forEach(function(key) {
if (options[key]) {
if (typeof options[key] != "object") options[key] = {};
if (!(name in options[key])) options[key][name] = options[name];
}
});
}
}
function init_cache(cache) {
if (!cache) return;
if (!("props" in cache)) {
cache.props = new Dictionary();
} else if (!(cache.props instanceof Dictionary)) {
cache.props = Dictionary.fromObject(cache.props);
}
}
function to_json(cache) {
return {
props: cache.props.toObject()
};
}
function minify(files, options) {
try {
options = defaults(options, {
compress: {},
enclose: false,
ie8: false,
keep_fnames: false,
mangle: {},
nameCache: null,
output: {},
parse: {},
rename: undefined,
sourceMap: false,
timings: false,
toplevel: false,
validate: false,
warnings: false,
wrap: false,
}, true);
if (options.validate) AST_Node.enable_validation();
var timings = options.timings && {
start: Date.now()
};
if (options.rename === undefined) {
options.rename = options.compress && options.mangle;
}
set_shorthand("ie8", options, [ "compress", "mangle", "output" ]);
set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
set_shorthand("toplevel", options, [ "compress", "mangle" ]);
var quoted_props;
if (options.mangle) {
options.mangle = defaults(options.mangle, {
cache: options.nameCache && (options.nameCache.vars || {}),
eval: false,
ie8: false,
keep_fnames: false,
properties: false,
reserved: [],
toplevel: false,
}, true);
if (options.mangle.properties) {
if (typeof options.mangle.properties != "object") {
options.mangle.properties = {};
}
if (options.mangle.properties.keep_quoted) {
quoted_props = options.mangle.properties.reserved;
if (!Array.isArray(quoted_props)) quoted_props = [];
options.mangle.properties.reserved = quoted_props;
}
if (options.nameCache && !("cache" in options.mangle.properties)) {
options.mangle.properties.cache = options.nameCache.props || {};
}
}
init_cache(options.mangle.cache);
init_cache(options.mangle.properties.cache);
}
if (options.sourceMap) {
options.sourceMap = defaults(options.sourceMap, {
content: null,
filename: null,
includeSources: false,
names: true,
root: null,
url: null,
}, true);
}
var warnings = [];
if (options.warnings) AST_Node.log_function(function(warning) {
warnings.push(warning);
}, options.warnings == "verbose");
if (timings) timings.parse = Date.now();
var toplevel;
if (files instanceof AST_Toplevel) {
toplevel = files;
} else {
if (typeof files == "string") {
files = [ files ];
}
options.parse = options.parse || {};
options.parse.toplevel = null;
var source_map_content = options.sourceMap && options.sourceMap.content;
if (typeof source_map_content == "string" && source_map_content != "inline") {
source_map_content = parse_source_map(source_map_content);
}
if (source_map_content) options.sourceMap.orig = Object.create(null);
for (var name in files) if (HOP(files, name)) {
options.parse.filename = name;
options.parse.toplevel = toplevel = parse(files[name], options.parse);
if (source_map_content == "inline") {
var inlined_content = read_source_map(name, toplevel);
if (inlined_content) {
options.sourceMap.orig[name] = parse_source_map(inlined_content);
}
} else if (source_map_content) {
options.sourceMap.orig[name] = source_map_content;
}
}
}
if (quoted_props) {
reserve_quoted_keys(toplevel, quoted_props);
}
[ "enclose", "wrap" ].forEach(function(action) {
var option = options[action];
if (!option) return;
var orig = toplevel.print_to_string().slice(0, -1);
toplevel = toplevel[action](option);
files[toplevel.start.file] = toplevel.print_to_string().replace(orig, "");
});
if (options.validate) toplevel.validate_ast();
if (timings) timings.rename = Date.now();
if (options.rename) {
toplevel.figure_out_scope(options.mangle);
toplevel.expand_names(options.mangle);
}
if (timings) timings.compress = Date.now();
if (options.compress) {
toplevel = new Compressor(options.compress).compress(toplevel);
if (options.validate) toplevel.validate_ast();
}
if (timings) timings.scope = Date.now();
if (options.mangle) toplevel.figure_out_scope(options.mangle);
if (timings) timings.mangle = Date.now();
if (options.mangle) {
toplevel.compute_char_frequency(options.mangle);
toplevel.mangle_names(options.mangle);
}
if (timings) timings.properties = Date.now();
if (options.mangle && options.mangle.properties) {
toplevel = mangle_properties(toplevel, options.mangle.properties);
}
if (timings) timings.output = Date.now();
var result = {};
if (options.output.ast) {
result.ast = toplevel;
}
if (!HOP(options.output, "code") || options.output.code) {
if (options.sourceMap) {
options.output.source_map = SourceMap(options.sourceMap);
if (options.sourceMap.includeSources) {
if (files instanceof AST_Toplevel) {
throw new Error("original source content unavailable");
} else for (var name in files) if (HOP(files, name)) {
options.output.source_map.setSourceContent(name, files[name]);
}
}
}
delete options.output.ast;
delete options.output.code;
var stream = OutputStream(options.output);
toplevel.print(stream);
result.code = stream.get();
if (options.sourceMap) {
result.map = options.output.source_map.toString();
var url = options.sourceMap.url;
if (url) {
result.code = result.code.replace(/\n\/\/# sourceMappingURL=\S+\s*$/, "");
if (url == "inline") {
result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(result.map);
} else {
result.code += "\n//# sourceMappingURL=" + url;
}
}
}
}
if (options.nameCache && options.mangle) {
if (options.mangle.cache) options.nameCache.vars = to_json(options.mangle.cache);
if (options.mangle.properties && options.mangle.properties.cache) {
options.nameCache.props = to_json(options.mangle.properties.cache);
}
}
if (timings) {
timings.end = Date.now();
result.timings = {
parse: 1e-3 * (timings.rename - timings.parse),
rename: 1e-3 * (timings.compress - timings.rename),
compress: 1e-3 * (timings.scope - timings.compress),
scope: 1e-3 * (timings.mangle - timings.scope),
mangle: 1e-3 * (timings.properties - timings.mangle),
properties: 1e-3 * (timings.output - timings.properties),
output: 1e-3 * (timings.end - timings.output),
total: 1e-3 * (timings.end - timings.start)
};
}
if (warnings.length) {
result.warnings = warnings;
}
return result;
} catch (ex) {
return { error: ex };
} finally {
AST_Node.disable_validation();
}
}

View File

@@ -1,7 +1,7 @@
/*********************************************************************** /***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor. A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS https://github.com/mishoo/UglifyJS2
-------------------------------- (C) --------------------------------- -------------------------------- (C) ---------------------------------
@@ -43,9 +43,11 @@
"use strict"; "use strict";
(function() { (function(){
function normalize_directives(body) {
var normalize_directives = function(body) {
var in_directive = true; var in_directive = true;
for (var i = 0; i < body.length; i++) { for (var i = 0; i < body.length; i++) {
if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) { if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) {
body[i] = new AST_Directive({ body[i] = new AST_Directive({
@@ -57,8 +59,9 @@
in_directive = false; in_directive = false;
} }
} }
return body; return body;
} };
var MOZ_TO_ME = { var MOZ_TO_ME = {
Program: function(M) { Program: function(M) {
@@ -111,7 +114,7 @@
var args = { var args = {
start : my_start_token(key), start : my_start_token(key),
end : my_end_token(M.value), end : my_end_token(M.value),
key : "" + key[key.type == "Identifier" ? "name" : "value"], key : key.type == "Identifier" ? key.name : key.value,
value : from_moz(M.value) value : from_moz(M.value)
}; };
if (M.kind == "init") return new AST_ObjectKeyVal(args); if (M.kind == "init") return new AST_ObjectKeyVal(args);
@@ -126,7 +129,7 @@
return new AST_Array({ return new AST_Array({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
elements : M.elements.map(function(elem) { elements : M.elements.map(function(elem){
return elem === null ? new AST_Hole() : from_moz(elem); return elem === null ? new AST_Hole() : from_moz(elem);
}) })
}); });
@@ -135,18 +138,14 @@
return new AST_Object({ return new AST_Object({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
properties : M.properties.map(function(prop) { properties : M.properties.map(function(prop){
prop.type = "Property"; prop.type = "Property";
return from_moz(prop) return from_moz(prop)
}) })
}); });
}, },
SequenceExpression: function(M) { SequenceExpression: function(M) {
return new AST_Sequence({ return AST_Seq.from_array(M.expressions.map(from_moz));
start : my_start_token(M),
end : my_end_token(M),
expressions: M.expressions.map(from_moz)
});
}, },
MemberExpression: function(M) { MemberExpression: function(M) {
return new (M.computed ? AST_Sub : AST_Dot)({ return new (M.computed ? AST_Sub : AST_Dot)({
@@ -165,7 +164,7 @@
}); });
}, },
VariableDeclaration: function(M) { VariableDeclaration: function(M) {
return new AST_Var({ return new (M.kind === "const" ? AST_Const : AST_Var)({
start : my_start_token(M), start : my_start_token(M),
end : my_end_token(M), end : my_end_token(M),
definitions : M.declarations.map(from_moz) definitions : M.declarations.map(from_moz)
@@ -177,17 +176,6 @@
end : my_end_token(M) end : my_end_token(M)
}; };
if (val === null) return new AST_Null(args); if (val === null) return new AST_Null(args);
var rx = M.regex;
if (rx && rx.pattern) {
// RegExpLiteral as per ESTree AST spec
args.value = new RegExp(rx.pattern, rx.flags);
args.value.raw_source = rx.pattern;
return new AST_RegExp(args);
} else if (rx) {
// support legacy RegExp
args.value = M.regex && M.raw ? M.raw : val;
return new AST_RegExp(args);
}
switch (typeof val) { switch (typeof val) {
case "string": case "string":
args.value = val; args.value = val;
@@ -197,12 +185,22 @@
return new AST_Number(args); return new AST_Number(args);
case "boolean": case "boolean":
return new (val ? AST_True : AST_False)(args); return new (val ? AST_True : AST_False)(args);
default:
var rx = M.regex;
if (rx && rx.pattern) {
// RegExpLiteral as per ESTree AST spec
args.value = new RegExp(rx.pattern, rx.flags).toString();
} else {
// support legacy RegExp
args.value = M.regex && M.raw ? M.raw : val;
}
return new AST_RegExp(args);
} }
}, },
Identifier: function(M) { Identifier: function(M) {
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2]; var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
return new ( p.type == "LabeledStatement" ? AST_Label return new ( p.type == "LabeledStatement" ? AST_Label
: p.type == "VariableDeclarator" && p.id === M ? AST_SymbolVar : p.type == "VariableDeclarator" && p.id === M ? (p.kind == "const" ? AST_SymbolConst : AST_SymbolVar)
: p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg) : p.type == "FunctionExpression" ? (p.id === M ? AST_SymbolLambda : AST_SymbolFunarg)
: p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg) : p.type == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
: p.type == "CatchClause" ? AST_SymbolCatch : p.type == "CatchClause" ? AST_SymbolCatch
@@ -212,14 +210,7 @@
end : my_end_token(M), end : my_end_token(M),
name : M.name name : M.name
}); });
}, }
ThisExpression: function(M) {
return new AST_This({
start : my_start_token(M),
end : my_end_token(M),
name : "this",
});
},
}; };
MOZ_TO_ME.UpdateExpression = MOZ_TO_ME.UpdateExpression =
@@ -252,6 +243,7 @@
map("VariableDeclarator", AST_VarDef, "id>name, init>value"); map("VariableDeclarator", AST_VarDef, "id>name, init>value");
map("CatchClause", AST_Catch, "param>argname, body%body"); map("CatchClause", AST_Catch, "param>argname, body%body");
map("ThisExpression", AST_This);
map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right"); map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right"); map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right"); map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
@@ -328,15 +320,15 @@
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) { def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
return { return {
type: "VariableDeclaration", type: "VariableDeclaration",
kind: "var", kind: M instanceof AST_Const ? "const" : "var",
declarations: M.definitions.map(to_moz) declarations: M.definitions.map(to_moz)
}; };
}); });
def_to_moz(AST_Sequence, function To_Moz_SequenceExpression(M) { def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) {
return { return {
type: "SequenceExpression", type: "SequenceExpression",
expressions: M.expressions.map(to_moz) expressions: M.to_array().map(to_moz)
}; };
}); });
@@ -409,24 +401,19 @@
var def = M.definition(); var def = M.definition();
return { return {
type: "Identifier", type: "Identifier",
name: def && def.mangled_name || M.name name: def ? def.mangled_name || def.name : M.name
}; };
}); });
def_to_moz(AST_This, function To_Moz_ThisExpression() {
return { type: "ThisExpression" };
});
def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) { def_to_moz(AST_RegExp, function To_Moz_RegExpLiteral(M) {
var flags = M.value.toString().match(/[gimuy]*$/)[0]; var value = M.value;
var value = "/" + M.value.raw_source + "/" + flags;
return { return {
type: "Literal", type: "Literal",
value: value, value: value,
raw: value, raw: value.toString(),
regex: { regex: {
pattern: M.value.raw_source, pattern: value.source,
flags: flags flags: value.toString().match(/[gimuy]*$/)[0]
} }
}; };
}); });
@@ -487,7 +474,7 @@
endpos : range ? range[0] : moznode.start, endpos : range ? range[0] : moznode.start,
raw : raw_token(moznode), raw : raw_token(moznode),
}); });
} };
function my_end_token(moznode) { function my_end_token(moznode) {
var loc = moznode.loc, end = loc && loc.end; var loc = moznode.loc, end = loc && loc.end;
@@ -502,7 +489,7 @@
endpos : range ? range[1] : moznode.end, endpos : range ? range[1] : moznode.end,
raw : raw_token(moznode), raw : raw_token(moznode),
}); });
} };
function map(moztype, mytype, propmap) { function map(moztype, mytype, propmap) {
var moz_to_me = "function From_Moz_" + moztype + "(M){\n"; var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
@@ -514,7 +501,7 @@
me_to_moz += "return {\n" + me_to_moz += "return {\n" +
"type: " + JSON.stringify(moztype); "type: " + JSON.stringify(moztype);
if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop) { if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop){
var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop); var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
if (!m) throw new Error("Can't understand property map: " + prop); if (!m) throw new Error("Can't understand property map: " + prop);
var moz = m[1], how = m[2], my = m[3]; var moz = m[1], how = m[2], my = m[3];
@@ -557,7 +544,7 @@
); );
MOZ_TO_ME[moztype] = moz_to_me; MOZ_TO_ME[moztype] = moz_to_me;
def_to_moz(mytype, me_to_moz); def_to_moz(mytype, me_to_moz);
} };
var FROM_MOZ_STACK = null; var FROM_MOZ_STACK = null;
@@ -566,28 +553,13 @@
var ret = node != null ? MOZ_TO_ME[node.type](node) : null; var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
FROM_MOZ_STACK.pop(); FROM_MOZ_STACK.pop();
return ret; return ret;
} };
AST_Node.from_mozilla_ast = function(node) { AST_Node.from_mozilla_ast = function(node){
var save_stack = FROM_MOZ_STACK; var save_stack = FROM_MOZ_STACK;
FROM_MOZ_STACK = []; FROM_MOZ_STACK = [];
var ast = from_moz(node); var ast = from_moz(node);
FROM_MOZ_STACK = save_stack; FROM_MOZ_STACK = save_stack;
ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_LabelRef) {
for (var level = 0, parent; parent = this.parent(level); level++) {
if (parent instanceof AST_Scope) break;
if (parent instanceof AST_LabeledStatement && parent.label.name == node.name) {
node.thedef = parent.label;
break;
}
}
if (!node.thedef) {
var s = node.start;
js_error("Undefined label " + node.name, s.file, s.line, s.col, s.pos);
}
}
}));
return ast; return ast;
}; };
@@ -607,24 +579,24 @@
} }
} }
return moznode; return moznode;
} };
function def_to_moz(mytype, handler) { function def_to_moz(mytype, handler) {
mytype.DEFMETHOD("to_mozilla_ast", function() { mytype.DEFMETHOD("to_mozilla_ast", function() {
return set_moz_loc(this, handler(this)); return set_moz_loc(this, handler(this));
}); });
} };
function to_moz(node) { function to_moz(node) {
return node != null ? node.to_mozilla_ast() : null; return node != null ? node.to_mozilla_ast() : null;
} };
function to_moz_block(node) { function to_moz_block(node) {
return { return {
type: "BlockStatement", type: "BlockStatement",
body: node.body.map(to_moz) body: node.body.map(to_moz)
}; };
} };
function to_moz_scope(type, node) { function to_moz_scope(type, node) {
var body = node.body.map(to_moz); var body = node.body.map(to_moz);
@@ -635,5 +607,5 @@
type: type, type: type,
body: body body: body
}; };
} };
})(); })();

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/*********************************************************************** /***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor. A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS https://github.com/mishoo/UglifyJS2
-------------------------------- (C) --------------------------------- -------------------------------- (C) ---------------------------------
@@ -43,137 +43,115 @@
"use strict"; "use strict";
function find_builtins(reserved) { function find_builtins() {
// NaN will be included due to Number.NaN // NaN will be included due to Number.NaN
[ var a = [
"null", "null",
"true", "true",
"false", "false",
"Infinity", "Infinity",
"-Infinity", "-Infinity",
"undefined", "undefined",
].forEach(add); ];
[ [ Object, Array, Function, Number,
Array, String, Boolean, Error, Math,
Boolean, Date, RegExp
Date, ].forEach(function(ctor){
Error,
Function,
Math,
Number,
Object,
RegExp,
String,
].forEach(function(ctor) {
Object.getOwnPropertyNames(ctor).map(add); Object.getOwnPropertyNames(ctor).map(add);
if (ctor.prototype) { if (ctor.prototype) {
Object.getOwnPropertyNames(ctor.prototype).map(add); Object.getOwnPropertyNames(ctor.prototype).map(add);
} }
}); });
function add(name) { function add(name) {
push_uniq(reserved, name); push_uniq(a, name);
} }
} return a;
function reserve_quoted_keys(ast, reserved) {
ast.walk(new TreeWalker(function(node) {
if (node instanceof AST_ObjectKeyVal && node.quote) {
add(node.key);
} else if (node instanceof AST_Sub) {
addStrings(node.property, add);
}
}));
function add(name) {
push_uniq(reserved, name);
}
}
function addStrings(node, add) {
node.walk(new TreeWalker(function(node) {
if (node instanceof AST_Sequence) {
addStrings(node.tail_node(), add);
} else if (node instanceof AST_String) {
add(node.value);
} else if (node instanceof AST_Conditional) {
addStrings(node.consequent, add);
addStrings(node.alternative, add);
}
return true;
}));
} }
function mangle_properties(ast, options) { function mangle_properties(ast, options) {
options = defaults(options, { options = defaults(options, {
builtins: false,
cache: null, cache: null,
debug: false, debug: false,
keep_quoted: false, ignore_quoted: false,
only_cache: false, only_cache: false,
regex: null, regex: null,
reserved: null, reserved: null,
}, true); });
var reserved = options.reserved; var reserved = options.reserved;
if (!Array.isArray(reserved)) reserved = []; if (reserved == null)
if (!options.builtins) find_builtins(reserved); reserved = find_builtins();
var cname = -1; var cache = options.cache;
var cache; if (cache == null) {
if (options.cache) { cache = {
cache = options.cache.props; cname: -1,
cache.each(function(mangled_name) { props: new Dictionary()
push_uniq(reserved, mangled_name); };
});
} else {
cache = new Dictionary();
} }
var regex = options.regex; var regex = options.regex;
var ignore_quoted = options.ignore_quoted;
// note debug is either false (disabled), or a string of the debug suffix to use (enabled). // note debug is either false (disabled), or a string of the debug suffix to use (enabled).
// note debug may be enabled as an empty string, which is falsey. Also treat passing 'true' // note debug may be enabled as an empty string, which is falsey. Also treat passing 'true'
// the same as passing an empty string. // the same as passing an empty string.
var debug = options.debug !== false; var debug = (options.debug !== false);
var debug_suffix; var debug_name_suffix;
if (debug) debug_suffix = options.debug === true ? "" : options.debug; if (debug) {
debug_name_suffix = (options.debug === true ? "" : options.debug);
}
var names_to_mangle = []; var names_to_mangle = [];
var unmangleable = []; var unmangleable = [];
var ignored = {};
// step 1: find candidates to mangle // step 1: find candidates to mangle
ast.walk(new TreeWalker(function(node) { ast.walk(new TreeWalker(function(node){
if (node instanceof AST_ObjectKeyVal) { if (node instanceof AST_ObjectKeyVal) {
add(node.key); add(node.key, ignore_quoted && node.quote);
} else if (node instanceof AST_ObjectProperty) { }
else if (node instanceof AST_ObjectProperty) {
// setter or getter, since KeyVal is handled above // setter or getter, since KeyVal is handled above
add(node.key.name); add(node.key.name);
} else if (node instanceof AST_Dot) { }
else if (node instanceof AST_Dot) {
add(node.property); add(node.property);
} else if (node instanceof AST_Sub) { }
addStrings(node.property, add); else if (node instanceof AST_Sub) {
} else if (node instanceof AST_Call addStrings(node.property, ignore_quoted);
&& node.expression.print_to_string() == "Object.defineProperty") {
addStrings(node.args[1], add);
} }
})); }));
// step 2: transform the tree, renaming properties // step 2: transform the tree, renaming properties
return ast.transform(new TreeTransformer(function(node) { return ast.transform(new TreeTransformer(function(node){
if (node instanceof AST_ObjectKeyVal) { if (node instanceof AST_ObjectKeyVal) {
node.key = mangle(node.key); if (!(ignore_quoted && node.quote))
} else if (node instanceof AST_ObjectProperty) { node.key = mangle(node.key);
}
else if (node instanceof AST_ObjectProperty) {
// setter or getter // setter or getter
node.key.name = mangle(node.key.name); node.key.name = mangle(node.key.name);
} else if (node instanceof AST_Dot) {
node.property = mangle(node.property);
} else if (!options.keep_quoted && node instanceof AST_Sub) {
node.property = mangleStrings(node.property);
} else if (node instanceof AST_Call
&& node.expression.print_to_string() == "Object.defineProperty") {
node.args[1] = mangleStrings(node.args[1]);
} }
else if (node instanceof AST_Dot) {
node.property = mangle(node.property);
}
else if (node instanceof AST_Sub) {
if (!ignore_quoted)
node.property = mangleStrings(node.property);
}
// else if (node instanceof AST_String) {
// if (should_mangle(node.value)) {
// AST_Node.warn(
// "Found \"{prop}\" property candidate for mangling in an arbitrary string [{file}:{line},{col}]", {
// file : node.start.file,
// line : node.start.line,
// col : node.start.col,
// prop : node.value
// }
// );
// }
// }
})); }));
// only function declarations after this line // only function declarations after this line
@@ -181,54 +159,106 @@ function mangle_properties(ast, options) {
function can_mangle(name) { function can_mangle(name) {
if (unmangleable.indexOf(name) >= 0) return false; if (unmangleable.indexOf(name) >= 0) return false;
if (reserved.indexOf(name) >= 0) return false; if (reserved.indexOf(name) >= 0) return false;
if (options.only_cache) return cache.has(name); if (options.only_cache) {
return cache.props.has(name);
}
if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false; if (/^-?[0-9]+(\.[0-9]+)?(e[+-][0-9]+)?$/.test(name)) return false;
return true; return true;
} }
function should_mangle(name) { function should_mangle(name) {
if (ignore_quoted && name in ignored) return false;
if (regex && !regex.test(name)) return false; if (regex && !regex.test(name)) return false;
if (reserved.indexOf(name) >= 0) return false; if (reserved.indexOf(name) >= 0) return false;
return cache.has(name) || names_to_mangle.indexOf(name) >= 0; return cache.props.has(name)
|| names_to_mangle.indexOf(name) >= 0;
} }
function add(name) { function add(name, ignore) {
if (can_mangle(name)) push_uniq(names_to_mangle, name); if (ignore) {
if (!should_mangle(name)) push_uniq(unmangleable, name); ignored[name] = true;
return;
}
if (can_mangle(name))
push_uniq(names_to_mangle, name);
if (!should_mangle(name)) {
push_uniq(unmangleable, name);
}
} }
function mangle(name) { function mangle(name) {
if (!should_mangle(name)) { if (!should_mangle(name)) {
return name; return name;
} }
var mangled = cache.get(name);
var mangled = cache.props.get(name);
if (!mangled) { if (!mangled) {
if (debug) { if (debug) {
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_. // debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
var debug_mangled = "_$" + name + "$" + debug_suffix + "_"; var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
if (can_mangle(debug_mangled)) mangled = debug_mangled;
if (can_mangle(debug_mangled) && !(ignore_quoted && debug_mangled in ignored)) {
mangled = debug_mangled;
}
} }
// either debug mode is off, or it is on and we could not use the mangled name // either debug mode is off, or it is on and we could not use the mangled name
if (!mangled) do { if (!mangled) {
mangled = base54(++cname); // note can_mangle() does not check if the name collides with the 'ignored' set
} while (!can_mangle(mangled)); // (filled with quoted properties when ignore_quoted set). Make sure we add this
cache.set(name, mangled); // check so we don't collide with a quoted name.
do {
mangled = base54(++cache.cname);
} while (!can_mangle(mangled) || (ignore_quoted && mangled in ignored));
}
cache.props.set(name, mangled);
} }
return mangled; return mangled;
} }
function addStrings(node, ignore) {
var out = {};
try {
(function walk(node){
node.walk(new TreeWalker(function(node){
if (node instanceof AST_Seq) {
walk(node.cdr);
return true;
}
if (node instanceof AST_String) {
add(node.value, ignore);
return true;
}
if (node instanceof AST_Conditional) {
walk(node.consequent);
walk(node.alternative);
return true;
}
throw out;
}));
})(node);
} catch(ex) {
if (ex !== out) throw ex;
}
}
function mangleStrings(node) { function mangleStrings(node) {
return node.transform(new TreeTransformer(function(node) { return node.transform(new TreeTransformer(function(node){
if (node instanceof AST_Sequence) { if (node instanceof AST_Seq) {
var last = node.expressions.length - 1; node.cdr = mangleStrings(node.cdr);
node.expressions[last] = mangleStrings(node.expressions[last]); }
} else if (node instanceof AST_String) { else if (node instanceof AST_String) {
node.value = mangle(node.value); node.value = mangle(node.value);
} else if (node instanceof AST_Conditional) { }
else if (node instanceof AST_Conditional) {
node.consequent = mangleStrings(node.consequent); node.consequent = mangleStrings(node.consequent);
node.alternative = mangleStrings(node.alternative); node.alternative = mangleStrings(node.alternative);
} }
return node; return node;
})); }));
} }
} }

View File

@@ -1,7 +1,7 @@
/*********************************************************************** /***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor. A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS https://github.com/mishoo/UglifyJS2
-------------------------------- (C) --------------------------------- -------------------------------- (C) ---------------------------------
@@ -43,62 +43,65 @@
"use strict"; "use strict";
function SymbolDef(id, scope, orig, init) { function SymbolDef(scope, index, orig) {
this.eliminated = 0;
this.global = false;
this.id = id;
this.init = init;
this.lambda = orig instanceof AST_SymbolLambda;
this.mangled_name = null;
this.name = orig.name; this.name = orig.name;
this.orig = [ orig ]; this.orig = [ orig ];
this.references = [];
this.replaced = 0;
this.scope = scope; this.scope = scope;
this.references = [];
this.global = false;
this.mangled_name = null;
this.undeclared = false; this.undeclared = false;
} this.index = index;
this.id = SymbolDef.next_id++;
};
SymbolDef.next_id = 1;
SymbolDef.prototype = { SymbolDef.prototype = {
unmangleable: function(options) { unmangleable: function(options) {
return this.global && !options.toplevel if (!options) options = {};
return (this.global && !options.toplevel)
|| this.undeclared || this.undeclared
|| !options.eval && this.scope.pinned() || (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|| options.keep_fnames || (options.keep_fnames
&& (this.orig[0] instanceof AST_SymbolLambda && (this.orig[0] instanceof AST_SymbolLambda
|| this.orig[0] instanceof AST_SymbolDefun); || this.orig[0] instanceof AST_SymbolDefun));
}, },
mangle: function(options) { mangle: function(options) {
var cache = options.cache && options.cache.props; var cache = options.cache && options.cache.props;
if (this.global && cache && cache.has(this.name)) { if (this.global && cache && cache.has(this.name)) {
this.mangled_name = cache.get(this.name); this.mangled_name = cache.get(this.name);
} else if (!this.mangled_name && !this.unmangleable(options)) { }
else if (!this.mangled_name && !this.unmangleable(options)) {
var s = this.scope;
var sym = this.orig[0];
if (!options.screw_ie8 && sym instanceof AST_SymbolLambda)
s = s.parent_scope;
var def; var def;
if (def = this.redefined()) { if (this.defun && (def = this.defun.variables.get(this.name))) {
this.mangled_name = def.mangled_name || def.name; this.mangled_name = def.mangled_name || def.name;
} else { } else
this.mangled_name = next_mangled_name(this.scope, options, this); this.mangled_name = s.next_mangled(options, this);
}
if (this.global && cache) { if (this.global && cache) {
cache.set(this.name, this.mangled_name); cache.set(this.name, this.mangled_name);
} }
} }
},
redefined: function() {
return this.defun && this.defun.variables.get(this.name);
} }
}; };
AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
options = defaults(options, { options = defaults(options, {
cache: null, cache: null,
ie8: false, screw_ie8: true,
}); });
// pass 1: setup scope chaining and handle definitions // pass 1: setup scope chaining and handle definitions
var self = this; var self = this;
var scope = self.parent_scope = null; var scope = self.parent_scope = null;
var labels = new Dictionary();
var defun = null; var defun = null;
var tw = new TreeWalker(function(node, descend) { var tw = new TreeWalker(function(node, descend){
if (node instanceof AST_Catch) { if (node instanceof AST_Catch) {
var save_scope = scope; var save_scope = scope;
scope = new AST_Scope(node); scope = new AST_Scope(node);
@@ -111,14 +114,28 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
node.init_scope_vars(scope); node.init_scope_vars(scope);
var save_scope = scope; var save_scope = scope;
var save_defun = defun; var save_defun = defun;
var save_labels = labels;
defun = scope = node; defun = scope = node;
labels = new Dictionary();
descend(); descend();
scope = save_scope; scope = save_scope;
defun = save_defun; defun = save_defun;
return true; labels = save_labels;
return true; // don't descend again in TreeWalker
}
if (node instanceof AST_LabeledStatement) {
var l = node.label;
if (labels.has(l.name)) {
throw new Error(string_template("Label {name} defined twice", l));
}
labels.set(l.name, l);
descend();
labels.del(l.name);
return true; // no descend again
} }
if (node instanceof AST_With) { if (node instanceof AST_With) {
for (var s = scope; s; s = s.parent_scope) s.uses_with = true; for (var s = scope; s; s = s.parent_scope)
s.uses_with = true;
return; return;
} }
if (node instanceof AST_Symbol) { if (node instanceof AST_Symbol) {
@@ -128,130 +145,109 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
node.thedef = node; node.thedef = node;
node.references = []; node.references = [];
} }
if (node instanceof AST_SymbolDefun) { if (node instanceof AST_SymbolLambda) {
// This should be defined in the parent scope, as we encounter the defun.def_function(node);
// AST_Defun node before getting to its AST_Symbol. }
(node.scope = defun.parent_scope.resolve()).def_function(node, defun); else if (node instanceof AST_SymbolDefun) {
} else if (node instanceof AST_SymbolLambda) { // Careful here, the scope where this should be defined is
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun); // the parent scope. The reason is that we enter a new
if (options.ie8) def.defun = defun.parent_scope.resolve(); // scope when we encounter the AST_Defun node (which is
} else if (node instanceof AST_SymbolVar) { // instanceof AST_Scope) but we get to the symbol a bit
defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined); // later.
(node.scope = defun.parent_scope).def_function(node);
}
else if (node instanceof AST_SymbolVar
|| node instanceof AST_SymbolConst) {
defun.def_variable(node);
if (defun !== scope) { if (defun !== scope) {
node.mark_enclosed(options); node.mark_enclosed(options);
var def = scope.find_variable(node); var def = scope.find_variable(node);
if (node.thedef !== def) { if (node.thedef !== def) {
node.thedef = def; node.thedef = def;
node.reference(options);
} }
node.reference(options);
} }
} else if (node instanceof AST_SymbolCatch) { }
else if (node instanceof AST_SymbolCatch) {
scope.def_variable(node).defun = defun; scope.def_variable(node).defun = defun;
} }
else if (node instanceof AST_LabelRef) {
var sym = labels.get(node.name);
if (!sym) throw new Error(string_template("Undefined label {name} [{line},{col}]", {
name: node.name,
line: node.start.line,
col: node.start.col
}));
node.thedef = sym;
}
}); });
self.next_def_id = 0;
self.walk(tw); self.walk(tw);
// pass 2: find back references and eval // pass 2: find back references and eval
self.globals = new Dictionary(); var func = null;
var tw = new TreeWalker(function(node) { var globals = self.globals = new Dictionary();
if (node instanceof AST_LoopControl) { var tw = new TreeWalker(function(node, descend){
if (node.label) node.label.thedef.references.push(node); if (node instanceof AST_Lambda) {
var prev_func = func;
func = node;
descend();
func = prev_func;
return true;
}
if (node instanceof AST_LoopControl && node.label) {
node.label.thedef.references.push(node);
return true; return true;
} }
if (node instanceof AST_SymbolRef) { if (node instanceof AST_SymbolRef) {
var name = node.name; var name = node.name;
if (name == "eval" && tw.parent() instanceof AST_Call) {
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
s.uses_eval = true;
}
}
var sym = node.scope.find_variable(name); var sym = node.scope.find_variable(name);
if (node.scope instanceof AST_Lambda && name == "arguments") {
node.scope.uses_arguments = true;
}
if (!sym) { if (!sym) {
sym = self.def_global(node); sym = self.def_global(node);
} else if (sym.scope instanceof AST_Lambda && name == "arguments") {
sym.scope.uses_arguments = true;
}
if (name == "eval") {
var parent = tw.parent();
if (parent.TYPE == "Call" && parent.expression === node) {
for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) {
s.uses_eval = true;
}
} else if (sym.undeclared) {
self.uses_eval = true;
}
} }
node.thedef = sym; node.thedef = sym;
node.reference(options); node.reference(options);
return true; return true;
} }
// ensure mangling works if catch reuses a scope variable
if (node instanceof AST_SymbolCatch) {
var def = node.definition().redefined();
if (def) for (var s = node.scope; s; s = s.parent_scope) {
push_uniq(s.enclosed, def);
if (s === def.scope) break;
}
return true;
}
}); });
self.walk(tw); self.walk(tw);
// pass 3: fix up any scoping issue with IE8 // pass 3: fix up any scoping issue with IE8
if (options.ie8) self.walk(new TreeWalker(function(node) { if (!options.screw_ie8) {
if (node instanceof AST_SymbolCatch) { self.walk(new TreeWalker(function(node, descend) {
var scope = node.thedef.defun; if (node instanceof AST_SymbolCatch) {
if (scope.name instanceof AST_SymbolLambda && scope.name.name == node.name) { var name = node.name;
scope = scope.parent_scope.resolve(); var refs = node.thedef.references;
var scope = node.thedef.defun;
var def = scope.find_variable(name) || self.globals.get(name) || scope.def_variable(node);
refs.forEach(function(ref) {
ref.thedef = def;
ref.reference(options);
});
node.thedef = def;
return true;
} }
redefine(node, scope); }));
return true; }
}
if (node instanceof AST_SymbolLambda) {
var def = node.thedef;
redefine(node, node.scope.parent_scope.resolve());
if (typeof node.thedef.init !== "undefined") {
node.thedef.init = false;
} else if (def.init) {
node.thedef.init = def.init;
}
return true;
}
}));
function redefine(node, scope) { if (options.cache) {
var name = node.name; this.cname = options.cache.cname;
var old_def = node.thedef;
var new_def = scope.find_variable(name);
if (new_def) {
var redef;
while (redef = new_def.redefined()) new_def = redef;
} else {
new_def = self.globals.get(name);
}
if (new_def) {
new_def.orig.push(node);
} else {
new_def = scope.def_variable(node);
}
old_def.defun = new_def.scope;
old_def.orig.concat(old_def.references).forEach(function(node) {
node.thedef = new_def;
node.reference(options);
});
if (old_def.lambda) new_def.lambda = true;
if (new_def.undeclared) self.variables.set(name, new_def);
} }
}); });
AST_Scope.DEFMETHOD("make_def", function(orig, init) { AST_Toplevel.DEFMETHOD("def_global", function(node){
var top = this;
while (top.parent_scope) top = top.parent_scope;
return new SymbolDef(++top.next_def_id, this, orig, init);
});
AST_Toplevel.DEFMETHOD("def_global", function(node) {
var globals = this.globals, name = node.name; var globals = this.globals, name = node.name;
if (globals.has(name)) { if (globals.has(name)) {
return globals.get(name); return globals.get(name);
} else { } else {
var g = this.make_def(node); var g = new SymbolDef(this, globals.size(), node);
g.undeclared = true; g.undeclared = true;
g.global = true; g.global = true;
globals.set(name, g); globals.set(name, g);
@@ -259,7 +255,7 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
} }
}); });
AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) { AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope){
this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions) this.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) this.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement this.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
@@ -269,10 +265,10 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
this.cname = -1; // the current index for mangling functions/variables this.cname = -1; // the current index for mangling functions/variables
}); });
AST_Lambda.DEFMETHOD("init_scope_vars", function() { AST_Lambda.DEFMETHOD("init_scope_vars", function(){
AST_Scope.prototype.init_scope_vars.apply(this, arguments); AST_Scope.prototype.init_scope_vars.apply(this, arguments);
this.uses_arguments = false; this.uses_arguments = false;
this.def_variable(new AST_SymbolFunarg({ this.def_variable(new AST_SymbolVar({
name: "arguments", name: "arguments",
start: this.start, start: this.start,
end: this.end end: this.end
@@ -281,7 +277,8 @@ AST_Lambda.DEFMETHOD("init_scope_vars", function() {
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) { AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
var def = this.definition(); var def = this.definition();
for (var s = this.scope; s; s = s.parent_scope) { var s = this.scope;
while (s) {
push_uniq(s.enclosed, def); push_uniq(s.enclosed, def);
if (options.keep_fnames) { if (options.keep_fnames) {
s.functions.each(function(d) { s.functions.each(function(d) {
@@ -289,6 +286,7 @@ AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
}); });
} }
if (s === def.scope) break; if (s === def.scope) break;
s = s.parent_scope;
} }
}); });
@@ -297,338 +295,362 @@ AST_Symbol.DEFMETHOD("reference", function(options) {
this.mark_enclosed(options); this.mark_enclosed(options);
}); });
AST_Scope.DEFMETHOD("find_variable", function(name) { AST_Scope.DEFMETHOD("find_variable", function(name){
if (name instanceof AST_Symbol) name = name.name; if (name instanceof AST_Symbol) name = name.name;
return this.variables.get(name) return this.variables.get(name)
|| (this.parent_scope && this.parent_scope.find_variable(name)); || (this.parent_scope && this.parent_scope.find_variable(name));
}); });
AST_Scope.DEFMETHOD("def_function", function(symbol, init) { AST_Scope.DEFMETHOD("def_function", function(symbol){
var def = this.def_variable(symbol, init); this.functions.set(symbol.name, this.def_variable(symbol));
if (!def.init || def.init instanceof AST_Defun) def.init = init;
this.functions.set(symbol.name, def);
return def;
}); });
AST_Scope.DEFMETHOD("def_variable", function(symbol, init) { AST_Scope.DEFMETHOD("def_variable", function(symbol){
var def = this.variables.get(symbol.name); var def;
if (def) { if (!this.variables.has(symbol.name)) {
def.orig.push(symbol); def = new SymbolDef(this, this.variables.size(), symbol);
if (def.init instanceof AST_Function) def.init = init;
} else {
def = this.make_def(symbol, init);
this.variables.set(symbol.name, def); this.variables.set(symbol.name, def);
def.global = !this.parent_scope; def.global = !this.parent_scope;
} else {
def = this.variables.get(symbol.name);
def.orig.push(symbol);
} }
return symbol.thedef = def; return symbol.thedef = def;
}); });
AST_Lambda.DEFMETHOD("resolve", return_this); AST_Scope.DEFMETHOD("next_mangled", function(options){
AST_Scope.DEFMETHOD("resolve", function() { var ext = this.enclosed;
return this.parent_scope.resolve(); out: while (true) {
var m = base54(++this.cname);
if (!is_identifier(m)) continue; // skip over "do"
// https://github.com/mishoo/UglifyJS2/issues/242 -- do not
// shadow a name excepted from mangling.
if (options.except.indexOf(m) >= 0) continue;
// we must ensure that the mangled name does not shadow a name
// from some parent scope that is referenced in this or in
// inner scopes.
for (var i = ext.length; --i >= 0;) {
var sym = ext[i];
var name = sym.mangled_name || (sym.unmangleable(options) && sym.name);
if (m == name) continue out;
}
return m;
}
}); });
AST_Toplevel.DEFMETHOD("resolve", return_this);
function names_in_use(scope, options) { AST_Function.DEFMETHOD("next_mangled", function(options, def){
var names = scope.names_in_use; // #179, #326
if (!names) { // in Safari strict mode, something like (function x(x){...}) is a syntax error;
scope.names_in_use = names = Object.create(scope.mangled_names || null); // a function expression's argument cannot shadow the function expression's name
scope.cname_holes = [];
var cache = options.cache && options.cache.props; var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition();
scope.enclosed.forEach(function(def) {
if (def.unmangleable(options)) names[def.name] = true; // the function's mangled_name is null when keep_fnames is true
if (def.global && cache && cache.has(def.name)) { var tricky_name = tricky_def ? tricky_def.mangled_name || tricky_def.name : null;
names[cache.get(def.name)] = true;
}
});
}
return names;
}
function next_mangled_name(scope, options, def) {
var in_use = names_in_use(scope, options);
var holes = scope.cname_holes;
var names = Object.create(null);
var scopes = [ scope ];
def.references.forEach(function(sym) {
var scope = sym.scope;
do {
if (scopes.indexOf(scope) < 0) {
for (var name in names_in_use(scope, options)) {
names[name] = true;
}
scopes.push(scope);
} else break;
} while (scope = scope.parent_scope);
});
var name;
for (var i = 0; i < holes.length; i++) {
name = base54(holes[i]);
if (names[name]) continue;
holes.splice(i, 1);
scope.names_in_use[name] = true;
return name;
}
while (true) { while (true) {
name = base54(++scope.cname); var name = AST_Lambda.prototype.next_mangled.call(this, options, def);
if (in_use[name] || RESERVED_WORDS[name] || options.reserved.has[name]) continue; if (!tricky_name || tricky_name != name)
if (!names[name]) break; return name;
holes.push(scope.cname);
} }
scope.names_in_use[name] = true; });
return name;
}
AST_Symbol.DEFMETHOD("unmangleable", function(options) { AST_Symbol.DEFMETHOD("unmangleable", function(options){
var def = this.definition(); return this.definition().unmangleable(options);
return !def || def.unmangleable(options);
}); });
// labels are always mangleable // labels are always mangleable
AST_Label.DEFMETHOD("unmangleable", return_false); AST_Label.DEFMETHOD("unmangleable", function(){
return false;
AST_Symbol.DEFMETHOD("unreferenced", function() {
return !this.definition().references.length && !this.scope.pinned();
}); });
AST_Symbol.DEFMETHOD("definition", function() { AST_Symbol.DEFMETHOD("unreferenced", function(){
return this.definition().references.length == 0
&& !(this.scope.uses_eval || this.scope.uses_with);
});
AST_Symbol.DEFMETHOD("undeclared", function(){
return this.definition().undeclared;
});
AST_LabelRef.DEFMETHOD("undeclared", function(){
return false;
});
AST_Label.DEFMETHOD("undeclared", function(){
return false;
});
AST_Symbol.DEFMETHOD("definition", function(){
return this.thedef; return this.thedef;
}); });
AST_Symbol.DEFMETHOD("global", function() { AST_Symbol.DEFMETHOD("global", function(){
return this.definition().global; return this.definition().global;
}); });
function _default_mangler_options(options) { AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
options = defaults(options, { return defaults(options, {
eval : false, eval : false,
ie8 : false, except : [],
keep_fnames : false, keep_fnames : false,
reserved : [], screw_ie8 : true,
sort : false, // Ignored. Flag retained for backwards compatibility.
toplevel : false, toplevel : false,
}); });
if (!Array.isArray(options.reserved)) options.reserved = []; });
// Never mangle arguments
push_uniq(options.reserved, "arguments");
options.reserved.has = makePredicate(options.reserved);
return options;
}
AST_Toplevel.DEFMETHOD("mangle_names", function(options) { AST_Toplevel.DEFMETHOD("mangle_names", function(options){
options = _default_mangler_options(options); options = this._default_mangler_options(options);
// Never mangle arguments
options.except.push('arguments');
// We only need to mangle declaration nodes. Special logic wired // We only need to mangle declaration nodes. Special logic wired
// into the code generator will display the mangled name if it's // into the code generator will display the mangled name if it's
// present (and for AST_SymbolRef-s it'll use the mangled name of // present (and for AST_SymbolRef-s it'll use the mangled name of
// the AST_SymbolDeclaration that it points to). // the AST_SymbolDeclaration that it points to).
var lname = -1; var lname = -1;
var to_mangle = [];
if (options.cache && options.cache.props) { if (options.cache) {
var mangled_names = this.mangled_names = Object.create(null); this.globals.each(function(symbol){
options.cache.props.each(function(mangled_name) { if (options.except.indexOf(symbol.name) < 0) {
mangled_names[mangled_name] = true; to_mangle.push(symbol);
}
}); });
} }
var redefined = []; var tw = new TreeWalker(function(node, descend){
var tw = new TreeWalker(function(node, descend) {
if (node instanceof AST_LabeledStatement) { if (node instanceof AST_LabeledStatement) {
// lname is incremented when we get to the AST_Label // lname is incremented when we get to the AST_Label
var save_nesting = lname; var save_nesting = lname;
descend(); descend();
lname = save_nesting; lname = save_nesting;
return true; return true; // don't descend again in TreeWalker
} }
if (node instanceof AST_Scope) { if (node instanceof AST_Scope) {
descend(); var p = tw.parent(), a = [];
if (options.cache && node instanceof AST_Toplevel) { node.variables.each(function(symbol){
node.globals.each(mangle); if (options.except.indexOf(symbol.name) < 0) {
} a.push(symbol);
if (node instanceof AST_Defun && tw.has_directive("use asm")) { }
var sym = new AST_SymbolRef(node.name);
sym.scope = node;
sym.reference(options);
}
node.variables.each(function(def) {
if (!defer_redef(def)) mangle(def);
}); });
return true; to_mangle.push.apply(to_mangle, a);
return;
} }
if (node instanceof AST_Label) { if (node instanceof AST_Label) {
var name; var name;
do { do name = base54(++lname); while (!is_identifier(name));
name = base54(++lname);
} while (RESERVED_WORDS[name]);
node.mangled_name = name; node.mangled_name = name;
return true; return true;
} }
if (!options.ie8 && node instanceof AST_Catch) { if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
var def = node.argname.definition(); to_mangle.push(node.definition());
var redef = defer_redef(def, node.argname); return;
descend();
if (!redef) mangle(def);
return true;
} }
}); });
this.walk(tw); this.walk(tw);
redefined.forEach(mangle); to_mangle.forEach(function(def){ def.mangle(options) });
function mangle(def) { if (options.cache) {
if (options.reserved.has[def.name]) return; options.cache.cname = this.cname;
def.mangle(options);
} }
});
function defer_redef(def, node) { AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
var redef = def.redefined(); options = this._default_mangler_options(options);
if (!redef) return false; var tw = new TreeWalker(function(node){
redefined.push(def); if (node instanceof AST_Constant)
def.references.forEach(reference); base54.consider(node.print_to_string());
if (node) reference(node); else if (node instanceof AST_Return)
return true; base54.consider("return");
else if (node instanceof AST_Throw)
function reference(sym) { base54.consider("throw");
sym.thedef = redef; else if (node instanceof AST_Continue)
sym.reference(options); base54.consider("continue");
sym.thedef = def; else if (node instanceof AST_Break)
base54.consider("break");
else if (node instanceof AST_Debugger)
base54.consider("debugger");
else if (node instanceof AST_Directive)
base54.consider(node.value);
else if (node instanceof AST_While)
base54.consider("while");
else if (node instanceof AST_Do)
base54.consider("do while");
else if (node instanceof AST_If) {
base54.consider("if");
if (node.alternative) base54.consider("else");
} }
} else if (node instanceof AST_Var)
}); base54.consider("var");
else if (node instanceof AST_Const)
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) { base54.consider("const");
var cache = options.cache && options.cache.props; else if (node instanceof AST_Lambda)
var avoid = Object.create(null); base54.consider("function");
options.reserved.forEach(to_avoid); else if (node instanceof AST_For)
this.globals.each(add_def); base54.consider("for");
this.walk(new TreeWalker(function(node) { else if (node instanceof AST_ForIn)
if (node instanceof AST_Scope) node.variables.each(add_def); base54.consider("for in");
if (node instanceof AST_SymbolCatch) add_def(node.definition()); else if (node instanceof AST_Switch)
})); base54.consider("switch");
return avoid; else if (node instanceof AST_Case)
base54.consider("case");
function to_avoid(name) { else if (node instanceof AST_Default)
avoid[name] = true; base54.consider("default");
} else if (node instanceof AST_With)
base54.consider("with");
function add_def(def) { else if (node instanceof AST_ObjectSetter)
var name = def.name; base54.consider("set" + node.key);
if (def.global && cache && cache.has(name)) name = cache.get(name); else if (node instanceof AST_ObjectGetter)
else if (!def.unmangleable(options)) return; base54.consider("get" + node.key);
to_avoid(name); else if (node instanceof AST_ObjectKeyVal)
} base54.consider(node.key);
}); else if (node instanceof AST_New)
base54.consider("new");
AST_Toplevel.DEFMETHOD("expand_names", function(options) { else if (node instanceof AST_This)
base54.reset(); base54.consider("this");
else if (node instanceof AST_Try)
base54.consider("try");
else if (node instanceof AST_Catch)
base54.consider("catch");
else if (node instanceof AST_Finally)
base54.consider("finally");
else if (node instanceof AST_Symbol && node.unmangleable(options))
base54.consider(node.name);
else if (node instanceof AST_Unary || node instanceof AST_Binary)
base54.consider(node.operator);
else if (node instanceof AST_Dot)
base54.consider(node.property);
});
this.walk(tw);
base54.sort(); base54.sort();
options = _default_mangler_options(options);
var avoid = this.find_colliding_names(options);
var cname = 0;
this.globals.each(rename);
this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope) node.variables.each(rename);
if (node instanceof AST_SymbolCatch) rename(node.definition());
}));
function next_name() {
var name;
do {
name = base54(cname++);
} while (avoid[name] || RESERVED_WORDS[name]);
return name;
}
function rename(def) {
if (def.global && options.cache) return;
if (def.unmangleable(options)) return;
if (options.reserved.has[def.name]) return;
var redef = def.redefined();
var name = redef ? redef.rename || redef.name : next_name();
def.rename = name;
def.orig.concat(def.references).forEach(function(sym) {
if (sym.definition() === def) sym.name = name;
});
}
});
AST_Node.DEFMETHOD("tail_node", return_this);
AST_Sequence.DEFMETHOD("tail_node", function() {
return this.expressions[this.expressions.length - 1];
});
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
options = _default_mangler_options(options);
base54.reset();
try {
AST_Node.prototype.print = function(stream, force_parens) {
this._print(stream, force_parens);
if (this instanceof AST_Symbol && !this.unmangleable(options)) {
base54.consider(this.name, -1);
} else if (options.properties) {
if (this instanceof AST_Dot) {
base54.consider(this.property, -1);
} else if (this instanceof AST_Sub) {
skip_string(this.property);
}
}
};
base54.consider(this.print_to_string(), 1);
} finally {
AST_Node.prototype.print = AST_Node.prototype._print;
}
base54.sort();
function skip_string(node) {
if (node instanceof AST_String) {
base54.consider(node.value, -1);
} else if (node instanceof AST_Conditional) {
skip_string(node.consequent);
skip_string(node.alternative);
} else if (node instanceof AST_Sequence) {
skip_string(node.tail_node());
}
}
}); });
var base54 = (function() { var base54 = (function() {
var freq = Object.create(null); var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
function init(chars) {
var array = [];
for (var i = 0; i < chars.length; i++) {
var ch = chars[i];
array.push(ch);
freq[ch] = -1e-2 * i;
}
return array;
}
var digits = init("0123456789");
var leading = init("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_");
var chars, frequency; var chars, frequency;
function reset() { function reset() {
frequency = Object.create(freq); frequency = Object.create(null);
chars = string.split("").map(function(ch){ return ch.charCodeAt(0) });
chars.forEach(function(ch){ frequency[ch] = 0 });
} }
base54.consider = function(str, delta) { base54.consider = function(str){
for (var i = str.length; --i >= 0;) { for (var i = str.length; --i >= 0;) {
frequency[str[i]] += delta; var code = str.charCodeAt(i);
if (code in frequency) ++frequency[code];
} }
}; };
function compare(a, b) {
return frequency[b] - frequency[a];
}
base54.sort = function() { base54.sort = function() {
chars = leading.sort(compare).concat(digits.sort(compare)); chars = mergeSort(chars, function(a, b){
if (is_digit(a) && !is_digit(b)) return 1;
if (is_digit(b) && !is_digit(a)) return -1;
return frequency[b] - frequency[a];
});
}; };
base54.reset = reset; base54.reset = reset;
reset(); reset();
base54.get = function(){ return chars };
base54.freq = function(){ return frequency };
function base54(num) { function base54(num) {
var ret = "", base = 54; var ret = "", base = 54;
num++; num++;
do { do {
num--; num--;
ret += chars[num % base]; ret += String.fromCharCode(chars[num % base]);
num = Math.floor(num / base); num = Math.floor(num / base);
base = 64; base = 64;
} while (num > 0); } while (num > 0);
return ret; return ret;
} };
return base54; return base54;
})(); })();
AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
options = defaults(options, {
assign_to_global : true,
eval : true,
func_arguments : true,
nested_defuns : true,
undeclared : false, // this makes a lot of noise
unreferenced : true,
});
var tw = new TreeWalker(function(node){
if (options.undeclared
&& node instanceof AST_SymbolRef
&& node.undeclared())
{
// XXX: this also warns about JS standard names,
// i.e. Object, Array, parseInt etc. Should add a list of
// exceptions.
AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", {
name: node.name,
file: node.start.file,
line: node.start.line,
col: node.start.col
});
}
if (options.assign_to_global)
{
var sym = null;
if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef)
sym = node.left;
else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef)
sym = node.init;
if (sym
&& (sym.undeclared()
|| (sym.global() && sym.scope !== sym.definition().scope))) {
AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", {
msg: sym.undeclared() ? "Accidental global?" : "Assignment to global",
name: sym.name,
file: sym.start.file,
line: sym.start.line,
col: sym.start.col
});
}
}
if (options.eval
&& node instanceof AST_SymbolRef
&& node.undeclared()
&& node.name == "eval") {
AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
}
if (options.unreferenced
&& (node instanceof AST_SymbolDeclaration || node instanceof AST_Label)
&& !(node instanceof AST_SymbolCatch)
&& node.unreferenced()) {
AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
type: node instanceof AST_Label ? "Label" : "Symbol",
name: node.name,
file: node.start.file,
line: node.start.line,
col: node.start.col
});
}
if (options.func_arguments
&& node instanceof AST_Lambda
&& node.uses_arguments) {
AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", {
name: node.name ? node.name.name : "anonymous",
file: node.start.file,
line: node.start.line,
col: node.start.col
});
}
if (options.nested_defuns
&& node instanceof AST_Defun
&& !(tw.parent() instanceof AST_Scope)) {
AST_Node.warn("Function {name} declared in nested statement \"{type}\" [{file}:{line},{col}]", {
name: node.name.name,
type: tw.parent().TYPE,
file: node.start.file,
line: node.start.line,
col: node.start.col
});
}
});
this.walk(tw);
});

View File

@@ -1,7 +1,7 @@
/*********************************************************************** /***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor. A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS https://github.com/mishoo/UglifyJS2
-------------------------------- (C) --------------------------------- -------------------------------- (C) ---------------------------------
@@ -43,149 +43,55 @@
"use strict"; "use strict";
var vlq_char = characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"); // a small wrapper around fitzgen's source-map library
var vlq_bits = vlq_char.reduce(function(map, ch, bits) {
map[ch] = bits;
return map;
}, Object.create(null));
function vlq_decode(indices, str) {
var value = 0;
var shift = 0;
for (var i = 0, j = 0; i < str.length; i++) {
var bits = vlq_bits[str[i]];
value += (bits & 31) << shift;
if (bits & 32) {
shift += 5;
} else {
indices[j++] += value & 1 ? 0x80000000 | -(value >> 1) : value >> 1;
value = shift = 0;
}
}
return j;
}
function vlq_encode(num) {
var result = "";
num = Math.abs(num) << 1 | num >>> 31;
do {
var bits = num & 31;
if (num >>>= 5) bits |= 32;
result += vlq_char[bits];
} while (num);
return result;
}
function create_array_map() {
var map = Object.create(null);
var array = [];
array.index = function(name) {
if (!HOP(map, name)) {
map[name] = array.length;
array.push(name);
}
return map[name];
};
return array;
}
function SourceMap(options) { function SourceMap(options) {
var sources = create_array_map(); options = defaults(options, {
var sources_content = options.includeSources && Object.create(null); file : null,
var names = create_array_map(); root : null,
var mappings = ""; orig : null,
if (options.orig) Object.keys(options.orig).forEach(function(name) {
var map = options.orig[name]; orig_line_diff : 0,
var indices = [ 0, 0, 1, 0, 0 ]; dest_line_diff : 0,
options.orig[name] = {
names: map.names,
mappings: map.mappings.split(/;/).map(function(line) {
indices[0] = 0;
return line.split(/,/).map(function(segment) {
return indices.slice(0, vlq_decode(indices, segment));
});
}),
sources: map.sources,
};
if (!sources_content || !map.sourcesContent) return;
for (var i = 0; i < map.sources.length; i++) {
var content = map.sourcesContent[i];
if (content) sources_content[map.sources[i]] = content;
}
}); });
var prev_source; var generator = new MOZ_SourceMap.SourceMapGenerator({
var generated_line = 1; file : options.file,
var generated_column = 0; sourceRoot : options.root
var source_index = 0; });
var original_line = 1; var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
var original_column = 0;
var name_index = 0; if (orig_map && Array.isArray(options.orig.sources)) {
return { orig_map._sources.toArray().forEach(function(source) {
add: options.orig ? function(source, gen_line, gen_col, orig_line, orig_col, name) { var sourceContent = orig_map.sourceContentFor(source, true);
var map = options.orig[source]; if (sourceContent) {
if (map) { generator.setSourceContent(source, sourceContent);
var segments = map.mappings[orig_line - 1];
if (!segments) return;
var indices;
for (var i = 0; i < segments.length; i++) {
var col = segments[i][0];
if (orig_col >= col) indices = segments[i];
if (orig_col <= col) break;
}
if (!indices || indices.length < 4) {
source = null;
} else {
source = map.sources[indices[1]];
orig_line = indices[2];
orig_col = indices[3];
if (indices.length > 4) name = map.names[indices[4]];
}
} }
add(source, gen_line, gen_col, orig_line, orig_col, name); });
} : add, }
setSourceContent: sources_content ? function(source, content) {
sources_content[source] = content;
} : noop,
toString: function() {
return JSON.stringify({
version: 3,
file: options.filename || undefined,
sourceRoot: options.root || undefined,
sources: sources,
sourcesContent: sources_content ? sources.map(function(source) {
return sources_content[source] || null;
}) : undefined,
names: names,
mappings: mappings,
});
}
};
function add(source, gen_line, gen_col, orig_line, orig_col, name) { function add(source, gen_line, gen_col, orig_line, orig_col, name) {
if (prev_source == null && source == null) return; if (orig_map) {
prev_source = source; var info = orig_map.originalPositionFor({
if (generated_line < gen_line) { line: orig_line,
generated_column = 0; column: orig_col
do { });
mappings += ";"; if (info.source === null) {
} while (++generated_line < gen_line); return;
} else if (mappings) { }
mappings += ","; source = info.source;
orig_line = info.line;
orig_col = info.column;
name = info.name || name;
} }
mappings += vlq_encode(gen_col - generated_column); generator.addMapping({
generated_column = gen_col; generated : { line: gen_line + options.dest_line_diff, column: gen_col },
if (source == null) return; original : { line: orig_line + options.orig_line_diff, column: orig_col },
var src_idx = sources.index(source); source : source,
mappings += vlq_encode(src_idx - source_index); name : name
source_index = src_idx; });
mappings += vlq_encode(orig_line - original_line); };
original_line = orig_line; return {
mappings += vlq_encode(orig_col - original_column); add : add,
original_column = orig_col; get : function() { return generator },
if (options.names && name != null) { toString : function() { return JSON.stringify(generator.toJSON()); }
var name_idx = names.index(name); };
mappings += vlq_encode(name_idx - name_index); };
name_index = name_idx;
}
}
}

View File

@@ -1,7 +1,7 @@
/*********************************************************************** /***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor. A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS https://github.com/mishoo/UglifyJS2
-------------------------------- (C) --------------------------------- -------------------------------- (C) ---------------------------------
@@ -43,6 +43,8 @@
"use strict"; "use strict";
// Tree transformer helpers.
function TreeTransformer(before, after) { function TreeTransformer(before, after) {
TreeWalker.call(this); TreeWalker.call(this);
this.before = before; this.before = before;
@@ -50,136 +52,167 @@ function TreeTransformer(before, after) {
} }
TreeTransformer.prototype = new TreeWalker; TreeTransformer.prototype = new TreeWalker;
(function(DEF) { (function(undefined){
function _(node, descend) {
node.DEFMETHOD("transform", function(tw, in_list){
var x, y;
tw.push(this);
if (tw.before) x = tw.before(this, descend, in_list);
if (x === undefined) {
if (!tw.after) {
x = this;
descend(x, tw);
} else {
tw.stack[tw.stack.length - 1] = x = this;
descend(x, tw);
y = tw.after(x, in_list);
if (y !== undefined) x = y;
}
}
tw.pop(this);
return x;
});
};
function do_list(list, tw) { function do_list(list, tw) {
return List(list, function(node) { return MAP(list, function(node){
return node.transform(tw, true); return node.transform(tw, true);
}); });
} };
DEF(AST_Node, noop); _(AST_Node, noop);
DEF(AST_LabeledStatement, function(self, tw) {
_(AST_LabeledStatement, function(self, tw){
self.label = self.label.transform(tw); self.label = self.label.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_SimpleStatement, function(self, tw) {
_(AST_SimpleStatement, function(self, tw){
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_Block, function(self, tw) {
_(AST_Block, function(self, tw){
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Do, function(self, tw) {
self.body = self.body.transform(tw); _(AST_DWLoop, function(self, tw){
self.condition = self.condition.transform(tw);
});
DEF(AST_While, function(self, tw) {
self.condition = self.condition.transform(tw); self.condition = self.condition.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_For, function(self, tw) {
_(AST_For, function(self, tw){
if (self.init) self.init = self.init.transform(tw); if (self.init) self.init = self.init.transform(tw);
if (self.condition) self.condition = self.condition.transform(tw); if (self.condition) self.condition = self.condition.transform(tw);
if (self.step) self.step = self.step.transform(tw); if (self.step) self.step = self.step.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_ForIn, function(self, tw) {
_(AST_ForIn, function(self, tw){
self.init = self.init.transform(tw); self.init = self.init.transform(tw);
self.object = self.object.transform(tw); self.object = self.object.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_With, function(self, tw) {
_(AST_With, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
}); });
DEF(AST_Exit, function(self, tw) {
_(AST_Exit, function(self, tw){
if (self.value) self.value = self.value.transform(tw); if (self.value) self.value = self.value.transform(tw);
}); });
DEF(AST_LoopControl, function(self, tw) {
_(AST_LoopControl, function(self, tw){
if (self.label) self.label = self.label.transform(tw); if (self.label) self.label = self.label.transform(tw);
}); });
DEF(AST_If, function(self, tw) {
_(AST_If, function(self, tw){
self.condition = self.condition.transform(tw); self.condition = self.condition.transform(tw);
self.body = self.body.transform(tw); self.body = self.body.transform(tw);
if (self.alternative) self.alternative = self.alternative.transform(tw); if (self.alternative) self.alternative = self.alternative.transform(tw);
}); });
DEF(AST_Switch, function(self, tw) {
_(AST_Switch, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Case, function(self, tw) {
_(AST_Case, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Try, function(self, tw) {
_(AST_Try, function(self, tw){
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
if (self.bcatch) self.bcatch = self.bcatch.transform(tw); if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
if (self.bfinally) self.bfinally = self.bfinally.transform(tw); if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
}); });
DEF(AST_Catch, function(self, tw) {
_(AST_Catch, function(self, tw){
self.argname = self.argname.transform(tw); self.argname = self.argname.transform(tw);
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Definitions, function(self, tw) {
_(AST_Definitions, function(self, tw){
self.definitions = do_list(self.definitions, tw); self.definitions = do_list(self.definitions, tw);
}); });
DEF(AST_VarDef, function(self, tw) {
_(AST_VarDef, function(self, tw){
self.name = self.name.transform(tw); self.name = self.name.transform(tw);
if (self.value) self.value = self.value.transform(tw); if (self.value) self.value = self.value.transform(tw);
}); });
DEF(AST_Lambda, function(self, tw) {
_(AST_Lambda, function(self, tw){
if (self.name) self.name = self.name.transform(tw); if (self.name) self.name = self.name.transform(tw);
self.argnames = do_list(self.argnames, tw); self.argnames = do_list(self.argnames, tw);
self.body = do_list(self.body, tw); self.body = do_list(self.body, tw);
}); });
DEF(AST_Call, function(self, tw) {
_(AST_Call, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.args = do_list(self.args, tw); self.args = do_list(self.args, tw);
}); });
DEF(AST_Sequence, function(self, tw) {
self.expressions = do_list(self.expressions, tw); _(AST_Seq, function(self, tw){
self.car = self.car.transform(tw);
self.cdr = self.cdr.transform(tw);
}); });
DEF(AST_Dot, function(self, tw) {
_(AST_Dot, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
}); });
DEF(AST_Sub, function(self, tw) {
_(AST_Sub, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
self.property = self.property.transform(tw); self.property = self.property.transform(tw);
}); });
DEF(AST_Unary, function(self, tw) {
_(AST_Unary, function(self, tw){
self.expression = self.expression.transform(tw); self.expression = self.expression.transform(tw);
}); });
DEF(AST_Binary, function(self, tw) {
_(AST_Binary, function(self, tw){
self.left = self.left.transform(tw); self.left = self.left.transform(tw);
self.right = self.right.transform(tw); self.right = self.right.transform(tw);
}); });
DEF(AST_Conditional, function(self, tw) {
_(AST_Conditional, function(self, tw){
self.condition = self.condition.transform(tw); self.condition = self.condition.transform(tw);
self.consequent = self.consequent.transform(tw); self.consequent = self.consequent.transform(tw);
self.alternative = self.alternative.transform(tw); self.alternative = self.alternative.transform(tw);
}); });
DEF(AST_Array, function(self, tw) {
_(AST_Array, function(self, tw){
self.elements = do_list(self.elements, tw); self.elements = do_list(self.elements, tw);
}); });
DEF(AST_Object, function(self, tw) {
_(AST_Object, function(self, tw){
self.properties = do_list(self.properties, tw); self.properties = do_list(self.properties, tw);
}); });
DEF(AST_ObjectProperty, function(self, tw) {
_(AST_ObjectProperty, function(self, tw){
self.value = self.value.transform(tw); self.value = self.value.transform(tw);
}); });
})(function(node, descend) {
node.DEFMETHOD("transform", function(tw, in_list) { })();
var x, y;
tw.push(this);
if (tw.before) x = tw.before(this, descend, in_list);
if (typeof x === "undefined") {
x = this;
descend(x, tw);
if (tw.after) {
y = tw.after(x, in_list);
if (typeof y !== "undefined") x = y;
}
}
tw.pop();
return x;
});
});

View File

@@ -1,7 +1,7 @@
/*********************************************************************** /***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor. A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS https://github.com/mishoo/UglifyJS2
-------------------------------- (C) --------------------------------- -------------------------------- (C) ---------------------------------
@@ -43,25 +43,40 @@
"use strict"; "use strict";
function array_to_hash(a) {
var ret = Object.create(null);
for (var i = 0; i < a.length; ++i)
ret[a[i]] = true;
return ret;
};
function slice(a, start) {
return Array.prototype.slice.call(a, start || 0);
};
function characters(str) { function characters(str) {
return str.split(""); return str.split("");
} };
function member(name, array) { function member(name, array) {
return array.indexOf(name) >= 0; return array.indexOf(name) >= 0;
} };
function find_if(func, array) { function find_if(func, array) {
for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i]; for (var i = 0, n = array.length; i < n; ++i) {
} if (func(array[i]))
return array[i];
}
};
function repeat_string(str, i) { function repeat_string(str, i) {
if (i <= 0) return ""; if (i <= 0) return "";
if (i == 1) return str; if (i == 1) return str;
var d = repeat_string(str, i >> 1); var d = repeat_string(str, i >> 1);
d += d; d += d;
return i & 1 ? d + str : d; if (i & 1) d += str;
} return d;
};
function configure_error_stack(fn) { function configure_error_stack(fn) {
Object.defineProperty(fn.prototype, "stack", { Object.defineProperty(fn.prototype, "stack", {
@@ -70,7 +85,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;
} }
} }
@@ -80,21 +95,27 @@ function configure_error_stack(fn) {
function DefaultsError(msg, defs) { function DefaultsError(msg, defs) {
this.message = msg; this.message = msg;
this.defs = defs; this.defs = defs;
} };
DefaultsError.prototype = Object.create(Error.prototype); DefaultsError.prototype = Object.create(Error.prototype);
DefaultsError.prototype.constructor = DefaultsError; DefaultsError.prototype.constructor = DefaultsError;
DefaultsError.prototype.name = "DefaultsError"; DefaultsError.prototype.name = "DefaultsError";
configure_error_stack(DefaultsError); configure_error_stack(DefaultsError);
DefaultsError.croak = function(msg, defs) {
throw new DefaultsError(msg, defs);
};
function defaults(args, defs, croak) { function defaults(args, defs, croak) {
if (croak) for (var i in args) { if (args === true)
if (HOP(args, i) && !HOP(defs, i)) throw new DefaultsError("`" + i + "` is not a supported option", defs); args = {};
var ret = args || {};
if (croak) for (var i in ret) if (HOP(ret, i) && !HOP(defs, i))
DefaultsError.croak("`" + i + "` is not a supported option", defs);
for (var i in defs) if (HOP(defs, i)) {
ret[i] = (args && HOP(args, i)) ? args[i] : defs[i];
} }
for (var i in args) { return ret;
if (HOP(args, i)) defs[i] = args[i]; };
}
return defs;
}
function merge(obj, ext) { function merge(obj, ext) {
var count = 0; var count = 0;
@@ -103,7 +124,7 @@ function merge(obj, ext) {
count++; count++;
} }
return count; return count;
} };
function noop() {} function noop() {}
function return_false() { return false; } function return_false() { return false; }
@@ -111,8 +132,8 @@ function return_true() { return true; }
function return_this() { return this; } function return_this() { return this; }
function return_null() { return null; } function return_null() { return null; }
var List = (function() { var MAP = (function(){
function List(a, f, backwards) { function MAP(a, f, backwards) {
var ret = [], top = [], i; var ret = [], top = [], i;
function doit() { function doit() {
var val = f(a[i], i); var val = f(a[i], i);
@@ -125,7 +146,8 @@ var List = (function() {
} else { } else {
top.push(val); top.push(val);
} }
} else if (val !== skip) { }
else if (val !== skip) {
if (val instanceof Splice) { if (val instanceof Splice) {
ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v); ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
} else { } else {
@@ -133,8 +155,8 @@ var List = (function() {
} }
} }
return is_last; return is_last;
} };
if (Array.isArray(a)) { if (a instanceof Array) {
if (backwards) { if (backwards) {
for (i = a.length; --i >= 0;) if (doit()) break; for (i = a.length; --i >= 0;) if (doit()) break;
ret.reverse(); ret.reverse();
@@ -142,59 +164,132 @@ var List = (function() {
} else { } else {
for (i = 0; i < a.length; ++i) if (doit()) break; for (i = 0; i < a.length; ++i) if (doit()) break;
} }
} else { }
else {
for (i in a) if (HOP(a, i)) if (doit()) break; for (i in a) if (HOP(a, i)) if (doit()) break;
} }
return top.concat(ret); return top.concat(ret);
}
List.is_op = function(val) {
return val === skip || val instanceof AtTop || val instanceof Last || val instanceof Splice;
}; };
List.at_top = function(val) { return new AtTop(val); }; MAP.at_top = function(val) { return new AtTop(val) };
List.splice = function(val) { return new Splice(val); }; MAP.splice = function(val) { return new Splice(val) };
List.last = function(val) { return new Last(val); }; MAP.last = function(val) { return new Last(val) };
var skip = List.skip = {}; var skip = MAP.skip = {};
function AtTop(val) { this.v = val; } function AtTop(val) { this.v = val };
function Splice(val) { this.v = val; } function Splice(val) { this.v = val };
function Last(val) { this.v = val; } function Last(val) { this.v = val };
return List; return MAP;
})(); })();
function push_uniq(array, el) { function push_uniq(array, el) {
if (array.indexOf(el) < 0) return array.push(el); if (array.indexOf(el) < 0)
} array.push(el);
};
function string_template(text, props) { function string_template(text, props) {
return text.replace(/\{(.+?)\}/g, function(str, p) { return text.replace(/\{(.+?)\}/g, function(str, p){
return props && props[p]; return props && props[p];
}); });
} };
function remove(array, el) { function remove(array, el) {
var index = array.indexOf(el); for (var i = array.length; --i >= 0;) {
if (index >= 0) array.splice(index, 1); if (array[i] === el) array.splice(i, 1);
} }
};
function makePredicate(words) { function mergeSort(array, cmp) {
if (!Array.isArray(words)) words = words.split(" "); if (array.length < 2) return array.slice();
var map = Object.create(null); function merge(a, b) {
words.forEach(function(word) { var r = [], ai = 0, bi = 0, i = 0;
map[word] = true; while (ai < a.length && bi < b.length) {
cmp(a[ai], b[bi]) <= 0
? r[i++] = a[ai++]
: r[i++] = b[bi++];
}
if (ai < a.length) r.push.apply(r, a.slice(ai));
if (bi < b.length) r.push.apply(r, b.slice(bi));
return r;
};
function _ms(a) {
if (a.length <= 1)
return a;
var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
left = _ms(left);
right = _ms(right);
return merge(left, right);
};
return _ms(array);
};
function set_difference(a, b) {
return a.filter(function(el){
return b.indexOf(el) < 0;
}); });
return map; };
}
function set_intersection(a, b) {
return a.filter(function(el){
return b.indexOf(el) >= 0;
});
};
// this function is taken from Acorn [1], written by Marijn Haverbeke
// [1] https://github.com/marijnh/acorn
function makePredicate(words) {
if (!(words instanceof Array)) words = words.split(" ");
var f = "", cats = [];
out: for (var i = 0; i < words.length; ++i) {
for (var j = 0; j < cats.length; ++j)
if (cats[j][0].length == words[i].length) {
cats[j].push(words[i]);
continue out;
}
cats.push([words[i]]);
}
function quote(word) {
return JSON.stringify(word).replace(/[\u2028\u2029]/g, function(s) {
switch (s) {
case "\u2028": return "\\u2028";
case "\u2029": return "\\u2029";
}
return s;
});
}
function compareTo(arr) {
if (arr.length == 1) return f += "return str === " + quote(arr[0]) + ";";
f += "switch(str){";
for (var i = 0; i < arr.length; ++i) f += "case " + quote(arr[i]) + ":";
f += "return true}return false;";
}
// When there are more than three length categories, an outer
// switch first dispatches on the lengths, to save on comparisons.
if (cats.length > 3) {
cats.sort(function(a, b) {return b.length - a.length;});
f += "switch(str.length){";
for (var i = 0; i < cats.length; ++i) {
var cat = cats[i];
f += "case " + cat[0].length + ":";
compareTo(cat);
}
f += "}";
// Otherwise, simply generate a flat `switch` statement.
} else {
compareTo(words);
}
return new Function("str", f);
};
function all(array, predicate) { function all(array, predicate) {
for (var i = array.length; --i >= 0;) for (var i = array.length; --i >= 0;)
if (!predicate(array[i], i)) if (!predicate(array[i]))
return false; return false;
return true; return true;
} };
function Dictionary() { function Dictionary() {
this._values = Object.create(null); this._values = Object.create(null);
this._size = 0; this._size = 0;
} };
Dictionary.prototype = { Dictionary.prototype = {
set: function(key, val) { set: function(key, val) {
if (!this.has(key)) ++this._size; if (!this.has(key)) ++this._size;
@@ -218,12 +313,6 @@ Dictionary.prototype = {
return this; return this;
}, },
has: function(key) { return ("$" + key) in this._values }, has: function(key) { return ("$" + key) in this._values },
all: function(predicate) {
for (var i in this._values)
if (!predicate(this._values[i], i.substr(1)))
return false;
return true;
},
each: function(f) { each: function(f) {
for (var i in this._values) for (var i in this._values)
f(this._values[i], i.substr(1)); f(this._values[i], i.substr(1));
@@ -237,13 +326,6 @@ Dictionary.prototype = {
ret.push(f(this._values[i], i.substr(1))); ret.push(f(this._values[i], i.substr(1)));
return ret; return ret;
}, },
clone: function() {
var ret = new Dictionary();
for (var i in this._values)
ret._values[i] = this._values[i];
ret._size = this._size;
return ret;
},
toObject: function() { return this._values } toObject: function() { return this._values }
}; };
Dictionary.fromObject = function(obj) { Dictionary.fromObject = function(obj) {
@@ -261,22 +343,20 @@ function HOP(obj, prop) {
// a statement. // a statement.
function first_in_statement(stack) { function first_in_statement(stack) {
var node = stack.parent(-1); var node = stack.parent(-1);
for (var i = 0, p; p = stack.parent(i++); node = p) { for (var i = 0, p; p = stack.parent(i); i++) {
if (p.TYPE == "Call") { if (p instanceof AST_Statement && p.body === node)
if (p.expression === node) continue; return true;
} else if (p instanceof AST_Binary) { if ((p instanceof AST_Seq && p.car === node ) ||
if (p.left === node) continue; (p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) ||
} else if (p instanceof AST_Conditional) { (p instanceof AST_Dot && p.expression === node ) ||
if (p.condition === node) continue; (p instanceof AST_Sub && p.expression === node ) ||
} else if (p instanceof AST_PropAccess) { (p instanceof AST_Conditional && p.condition === node ) ||
if (p.expression === node) continue; (p instanceof AST_Binary && p.left === node ) ||
} else if (p instanceof AST_Sequence) { (p instanceof AST_UnaryPostfix && p.expression === node ))
if (p.expressions[0] === node) continue; {
} else if (p instanceof AST_Statement) { node = p;
return p.body === node; } else {
} else if (p instanceof AST_UnaryPostfix) { return false;
if (p.expression === node) continue;
} }
return false;
} }
} }

View File

@@ -1,17 +1,23 @@
{ {
"name": "uglify-js", "name": "uglify-js",
"description": "JavaScript parser, mangler/compressor and beautifier toolkit", "description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"homepage": "http://lisperator.net/uglifyjs",
"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.10.1", "version": "2.8.27",
"engines": { "engines": {
"node": ">=0.8.0" "node": ">=0.8.0"
}, },
"maintainers": [ "maintainers": [
"Alex Lam <alexlamsl@gmail.com>",
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)" "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
], ],
"repository": "mishoo/UglifyJS", "repository": {
"type": "git",
"url": "https://github.com/mishoo/UglifyJS2.git"
},
"bugs": {
"url": "https://github.com/mishoo/UglifyJS2/issues"
},
"main": "tools/node.js", "main": "tools/node.js",
"bin": { "bin": {
"uglifyjs": "bin/uglifyjs" "uglifyjs": "bin/uglifyjs"
@@ -22,35 +28,24 @@
"tools", "tools",
"LICENSE" "LICENSE"
], ],
"dependencies": {
"source-map": "~0.5.1",
"yargs": "~3.10.0"
},
"devDependencies": { "devDependencies": {
"acorn": "~7.1.0", "acorn": "~5.0.3",
"semver": "~6.3.0" "mocha": "~2.3.4"
},
"optionalDependencies": {
"uglify-to-browserify": "~1.0.0"
},
"browserify": {
"transform": [
"uglify-to-browserify"
]
}, },
"scripts": { "scripts": {
"test": "node test/compress.js && node test/mocha.js" "test": "node test/run-tests.js"
}, },
"keywords": [ "keywords": ["uglify", "uglify-js", "minify", "minifier"]
"cli",
"compress",
"compressor",
"ecma",
"ecmascript",
"es",
"es5",
"javascript",
"js",
"jsmin",
"min",
"minification",
"minifier",
"minify",
"optimize",
"optimizer",
"pack",
"packer",
"parse",
"parser",
"uglifier",
"uglify"
]
} }

View File

@@ -4,45 +4,43 @@
"use strict"; "use strict";
var createHash = require("crypto").createHash; var createHash = require("crypto").createHash;
var fetch = require("./fetch"); var fork = require("child_process").fork;
var spawn = require("child_process").spawn;
var zlib = require("zlib");
var args = process.argv.slice(2); var args = process.argv.slice(2);
if (!args.length) args.push("-mc"); if (!args.length) {
args.unshift("bin/uglifyjs"); args.push("-mc", "warnings=false");
args.push("--timings"); }
args.push("--stats");
var urls = [ var urls = [
"https://code.jquery.com/jquery-3.4.1.js", "https://code.jquery.com/jquery-3.2.1.js",
"https://code.angularjs.org/1.7.8/angular.js", "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js",
"https://unpkg.com/mathjs@6.2.3/dist/math.js", "https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.9.0/math.js",
"https://unpkg.com/react@15.3.2/dist/react.js",
"https://cdnjs.cloudflare.com/ajax/libs/d3/5.12.0/d3.js",
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js", "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js", "https://unpkg.com/react@15.3.2/dist/react.js",
"https://cdnjs.cloudflare.com/ajax/libs/ember.js/2.12.2/ember.prod.js", "http://builds.emberjs.com/tags/v2.11.0/ember.prod.js",
"https://raw.githubusercontent.com/kangax/html-minifier/v4.0.0/dist/htmlminifier.js", "https://cdn.jsdelivr.net/lodash/4.17.4/lodash.js",
"https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.js",
]; ];
var results = {}; var results = {};
var remaining = 2 * urls.length; var remaining = 2 * urls.length;
function done() { function done() {
if (!--remaining) { if (!--remaining) {
var failures = []; var failures = [];
var sum = { input: 0, output: 0, gzip: 0 };
urls.forEach(function(url) { urls.forEach(function(url) {
var info = results[url]; var info = results[url];
console.log(); console.log();
console.log(url); console.log(url);
console.log(info.log); console.log(info.log);
var elapsed = 0;
info.log.replace(/: ([0-9]+\.[0-9]{3})s/g, function(match, time) {
elapsed += parseFloat(time);
});
console.log("Run-time:", elapsed.toFixed(3), "s");
console.log("Original:", info.input, "bytes"); console.log("Original:", info.input, "bytes");
console.log("Uglified:", info.output, "bytes"); console.log("Uglified:", info.output, "bytes");
console.log("GZipped: ", info.gzip, "bytes");
console.log("SHA1 sum:", info.sha1); console.log("SHA1 sum:", info.sha1);
if (info.code) { if (info.code) {
failures.push(url); failures.push(url);
} }
sum.input += info.input;
sum.output += info.output;
sum.gzip += info.gzip;
}); });
if (failures.length) { if (failures.length) {
console.error("Benchmark failed:"); console.error("Benchmark failed:");
@@ -50,13 +48,6 @@ function done() {
console.error(url); console.error(url);
}); });
process.exit(1); process.exit(1);
} else {
console.log();
console.log("Subtotal");
console.log();
console.log("Original:", sum.input, "bytes");
console.log("Uglified:", sum.output, "bytes");
console.log("GZipped: ", sum.gzip, "bytes");
} }
} }
} }
@@ -64,25 +55,17 @@ urls.forEach(function(url) {
results[url] = { results[url] = {
input: 0, input: 0,
output: 0, output: 0,
gzip: 0,
log: "" log: ""
}; };
fetch(url, function(err, res) { require(url.slice(0, url.indexOf(":"))).get(url, function(res) {
if (err) throw err; var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
var uglifyjs = spawn(process.argv[0], args, { silent: true });
res.on("data", function(data) { res.on("data", function(data) {
results[url].input += data.length; results[url].input += data.length;
}).pipe(uglifyjs.stdin); }).pipe(uglifyjs.stdin);
var sha1 = createHash("sha1");
uglifyjs.stdout.on("data", function(data) { uglifyjs.stdout.on("data", function(data) {
results[url].output += data.length; results[url].output += data.length;
}).pipe(zlib.createGzip({ }).pipe(createHash("sha1")).on("data", function(data) {
level: zlib.Z_BEST_COMPRESSION results[url].sha1 = data.toString("hex");
})).on("data", function(data) {
results[url].gzip += data.length;
sha1.update(data);
}).on("end", function() {
results[url].sha1 = sha1.digest("hex");
done(); done();
}); });
uglifyjs.stderr.setEncoding("utf8"); uglifyjs.stderr.setEncoding("utf8");

View File

@@ -1,462 +0,0 @@
"use strict";
require("../tools/exit");
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/options.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/UglifyJS/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);
options.validate = true;
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 toplevel = sandbox.has_toplevel(options);
var expected = stdout[toplevel ? 1 : 0];
var actual = run_code(result.code, toplevel);
if (typeof expected != "string" && typeof actual != "string" && expected.name == actual.name) {
actual = expected;
}
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 });
U.AST_Node.enable_validation();
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 {
input.validate_ast();
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);
}
}
var output_code = make_code(output, output_options);
if (expect != output_code) {
log([
"!!! failed",
"---INPUT---",
"{input}",
"---OUTPUT---",
"{output}",
"---EXPECTED---",
"{expected}",
"",
"",
].join("\n"), {
input: input_formatted,
output: output_code,
expected: expect
});
return false;
}
// expect == output
try {
output.validate_ast();
U.parse(output_code);
} 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_code,
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 = sandbox.has_toplevel({
compress: test.options,
mangle: test.mangle
});
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_code, 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;
}

67
test/compress/angular-inject.js vendored Normal file
View File

@@ -0,0 +1,67 @@
ng_inject_defun: {
options = {
angular: true
};
input: {
/*@ngInject*/
function Controller(dependency) {
return dependency;
}
}
expect: {
function Controller(dependency) {
return dependency;
}
Controller.$inject=['dependency']
}
}
ng_inject_assignment: {
options = {
angular: true
};
input: {
/*@ngInject*/
var Controller = function(dependency) {
return dependency;
}
}
expect: {
var Controller = function(dependency) {
return dependency;
}
Controller.$inject=['dependency']
}
}
ng_inject_inline: {
options = {
angular: true
};
input: {
angular.module('a').
factory('b',
/*@ngInject*/
function(dependency) {
return dependency;
}).
directive('c',
/*@ngInject*/
function(anotherDependency) {
return anotherDependency;
})
}
expect: {
angular.module('a').
factory('b',[
'dependency',
function(dependency) {
return dependency;
}]).
directive('c',[
'anotherDependency',
function(anotherDependency) {
return anotherDependency;
}])
}
}

View File

@@ -1,785 +0,0 @@
replace_index: {
options = {
arguments: true,
evaluate: true,
properties: true,
}
input: {
var arguments = [];
console.log(arguments[0]);
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(arguments) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function() {
var arguments;
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
}
expect: {
var arguments = [];
console.log(arguments[0]);
(function() {
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
(function(a, b) {
console.log(b, b, arguments.foo);
})("bar", 42);
(function(arguments) {
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
(function() {
var arguments;
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
}
expect_stdout: [
"undefined",
"42 42 undefined",
"42 42 undefined",
"a a undefined",
"42 42 undefined",
]
}
replace_index_strict: {
options = {
arguments: true,
evaluate: true,
properties: true,
reduce_vars: true,
}
input: {
"use strict";
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
}
expect: {
"use strict";
(function() {
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
(function(a, b) {
console.log(b, b, arguments.foo);
})("bar", 42);
}
expect_stdout: [
"42 42 undefined",
"42 42 undefined",
]
}
replace_index_keep_fargs: {
options = {
arguments: true,
evaluate: true,
keep_fargs: false,
properties: true,
}
input: {
var arguments = [];
console.log(arguments[0]);
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(arguments) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function() {
var arguments;
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
}
expect: {
var arguments = [];
console.log(arguments[0]);
(function(argument_0, argument_1) {
console.log(argument_1, argument_1, arguments.foo);
})("bar", 42);
(function(a, b) {
console.log(b, b, arguments.foo);
})("bar", 42);
(function(arguments) {
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
(function() {
var arguments;
console.log(arguments[1], arguments[1], arguments.foo);
})("bar", 42);
}
expect_stdout: [
"undefined",
"42 42 undefined",
"42 42 undefined",
"a a undefined",
"42 42 undefined",
]
}
replace_index_keep_fargs_strict: {
options = {
arguments: true,
evaluate: true,
keep_fargs: false,
properties: true,
reduce_vars: true,
}
input: {
"use strict";
(function() {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function(a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
}
expect: {
"use strict";
(function(argument_0, argument_1) {
console.log(argument_1, argument_1, arguments.foo);
})("bar", 42);
(function(a, b) {
console.log(b, b, arguments.foo);
})("bar", 42);
}
expect_stdout: [
"42 42 undefined",
"42 42 undefined",
]
}
modified: {
options = {
arguments: true,
}
input: {
(function(a, b) {
var c = arguments[0];
var d = arguments[1];
var a = "foo";
b++;
arguments[0] = "moo";
arguments[1] *= 2;
console.log(a, b, c, d, arguments[0], arguments[1]);
})("bar", 42);
}
expect: {
(function(a, b) {
var c = a;
var d = b;
var a = "foo";
b++;
a = "moo";
b *= 2;
console.log(a, b, c, d, a, b);
})("bar", 42);
}
expect_stdout: "moo 86 bar 42 moo 86"
}
modified_strict: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
"use strict";
(function(a, b) {
var c = arguments[0];
var d = arguments[1];
var a = "foo";
b++;
arguments[0] = "moo";
arguments[1] *= 2;
console.log(a, b, c, d, arguments[0], arguments[1]);
})("bar", 42);
}
expect: {
"use strict";
(function(a, b) {
var c = arguments[0];
var d = arguments[1];
var a = "foo";
b++;
arguments[0] = "moo";
arguments[1] *= 2;
console.log(a, b, c, d, arguments[0], arguments[1]);
})("bar", 42);
}
expect_stdout: "foo 43 bar 42 moo 84"
}
duplicate_argname: {
options = {
arguments: true,
}
input: {
(function(a, b, a) {
console.log(a, b, arguments[0], arguments[1], arguments[2]);
})("foo", 42, "bar");
}
expect: {
(function(a, b, a) {
console.log(a, b, arguments[0], b, a);
})("foo", 42, "bar");
}
expect_stdout: "bar 42 foo 42 bar"
}
issue_3273: {
options = {
arguments: true,
}
input: {
(function(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect: {
(function(a) {
console.log(a, a);
a++;
console.log(a, a);
})(0);
}
expect_stdout: [
"0 0",
"1 1",
]
}
issue_3273_no_call_arg: {
options = {
arguments: true,
}
input: {
(function(a) {
arguments[0] = "FAIL";
console.log(a);
})();
}
expect: {
(function(a) {
arguments[0] = "FAIL";
console.log(a);
})();
}
expect_stdout: "undefined"
}
issue_3273_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
(function(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect: {
(function(a) {
console.log(a, a);
a++;
console.log(a, a);
})(0);
}
expect_stdout: [
"0 0",
"1 1",
]
}
issue_3273_local_strict: {
options = {
arguments: true,
}
input: {
(function(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect: {
(function(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_local_strict_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
(function(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect: {
(function(a) {
"use strict";
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_global_strict: {
options = {
arguments: true,
}
input: {
"use strict";
(function(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect: {
"use strict";
(function(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect_stdout: [
"0 0",
"1 0",
]
}
issue_3273_global_strict_reduce_vars: {
options = {
arguments: true,
reduce_vars: true,
}
input: {
"use strict";
(function(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(0);
}
expect: {
"use strict";
(function(a) {
console.log(arguments[0], a);
arguments[0]++;
console.log(arguments[0], a);
})(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"
}

View File

@@ -15,10 +15,9 @@ holes_and_undefined: {
constant_join: { constant_join: {
options = { options = {
evaluate: true, unsafe : true,
strings: true, evaluate : true
unsafe: true, };
}
input: { input: {
var a = [ "foo", "bar", "baz" ].join(""); var a = [ "foo", "bar", "baz" ].join("");
var a1 = [ "foo", "bar", "baz" ].join(); var a1 = [ "foo", "bar", "baz" ].join();
@@ -65,10 +64,9 @@ constant_join: {
constant_join_2: { constant_join_2: {
options = { options = {
evaluate: true, unsafe : true,
strings: true, evaluate : true
unsafe: true, };
}
input: { input: {
var a = [ "foo", "bar", boo(), "baz", "x", "y" ].join(""); var a = [ "foo", "bar", boo(), "baz", "x", "y" ].join("");
var b = [ "foo", "bar", boo(), "baz", "x", "y" ].join("-"); var b = [ "foo", "bar", boo(), "baz", "x", "y" ].join("-");
@@ -95,12 +93,10 @@ constant_join_2: {
constant_join_3: { constant_join_3: {
options = { options = {
evaluate: true,
strings: true,
unsafe: true, unsafe: true,
} evaluate: true,
};
input: { input: {
var foo, bar, baz;
var a = [ null ].join(); var a = [ null ].join();
var b = [ , ].join(); var b = [ , ].join();
var c = [ , 1, , 3 ].join(); var c = [ , 1, , 3 ].join();
@@ -115,7 +111,6 @@ constant_join_3: {
var l = [ foo, bar + "baz" ].join(""); var l = [ foo, bar + "baz" ].join("");
} }
expect: { expect: {
var foo, bar, baz;
var a = ""; var a = "";
var b = ""; var b = "";
var c = ",1,,3"; var c = ",1,,3";
@@ -133,224 +128,50 @@ constant_join_3: {
for_loop: { for_loop: {
options = { options = {
evaluate: true, unsafe : true,
reduce_funcs: true, unused : true,
reduce_vars: true, evaluate : true,
unsafe: true, reduce_vars : true
unused: true, };
}
input: { input: {
function f0() { function f0() {
var a = [1, 2, 3]; var a = [1, 2, 3];
var b = 0; for (var i = 0; i < a.length; i++) {
for (var i = 0; i < a.length; i++) console.log(a[i]);
b += a[i]; }
return b;
} }
function f1() { function f1() {
var a = [1, 2, 3]; var a = [1, 2, 3];
var b = 0; for (var i = 0, len = a.length; i < len; i++) {
for (var i = 0, len = a.length; i < len; i++) console.log(a[i]);
b += a[i]; }
return b;
} }
function f2() { function f2() {
var a = [1, 2, 3]; var a = [1, 2, 3];
for (var i = 0; i < a.length; i++) for (var i = 0; i < a.length; i++) {
a[i]++; a[i]++;
return a[2]; }
} }
console.log(f0(), f1(), f2());
} }
expect: { expect: {
function f0() { function f0() {
var a = [1, 2, 3]; var a = [1, 2, 3];
var b = 0;
for (var i = 0; i < 3; i++) for (var i = 0; i < 3; i++)
b += a[i]; console.log(a[i]);
return b;
} }
function f1() { function f1() {
var a = [1, 2, 3]; var a = [1, 2, 3];
var b = 0;
for (var i = 0; i < 3; i++) for (var i = 0; i < 3; i++)
b += a[i]; console.log(a[i]);
return b;
} }
function f2() { function f2() {
var a = [1, 2, 3]; var a = [1, 2, 3];
for (var i = 0; i < a.length; i++) for (var i = 0; i < a.length; i++)
a[i]++; a[i]++;
return a[2];
}
console.log(f0(), f1(), f2());
}
expect_stdout: "6 6 4"
}
index: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a = [ 1, 2 ];
console.log(a[0], a[1]);
}
expect: {
console.log(1, 2);
}
expect_stdout: "1 2"
}
length: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a = [ 1, 2 ];
console.log(a.length);
}
expect: {
console.log(2);
}
expect_stdout: "2"
}
index_length: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var a = [ 1, 2 ];
console.log(a[0], a.length);
}
expect: {
console.log(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: []
} }

View File

@@ -2,7 +2,7 @@ ascii_only_true: {
options = {} options = {}
beautify = { beautify = {
ascii_only : true, ascii_only : true,
ie8 : false, screw_ie8 : true,
beautify : false, beautify : false,
} }
input: { input: {
@@ -13,14 +13,14 @@ ascii_only_true: {
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff"; "\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
} }
} }
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\0"+"\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}' expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\b\\t\\n\\v\\f\\r\\x0e\\x0f"+"\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f"+\' !"# ... }~\\x7f\\x80\\x81 ... \\xfe\\xff\\u0fff\\uffff\'}'
} }
ascii_only_false: { ascii_only_false: {
options = {} options = {}
beautify = { beautify = {
ascii_only : false, ascii_only : false,
ie8 : false, screw_ie8 : true,
beautify : false, beautify : false,
} }
input: { input: {
@@ -31,5 +31,6 @@ ascii_only_false: {
"\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff"; "\x20\x21\x22\x23 ... \x7d\x7e\x7f\x80\x81 ... \xfe\xff\u0fff\uffff";
} }
} }
expect_exact: 'function f(){return"\\x000\\x001\\x007\\x008\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}' expect_exact: 'function f(){return"\\x000\\x001\\x007\\08\\0"+"\\0\x01\x02\x03\x04\x05\x06\x07\\b\\t\\n\\v\\f\\r\x0e\x0f"+"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"+\' !"# ... }~\x7f\x80\x81 ... \xfe\xff\u0fff\uffff\'}'
} }

View File

@@ -1,25 +1,25 @@
asm_mixed: { asm_mixed: {
options = { options = {
assignments: true, sequences : true,
booleans: true, properties : true,
comparisons: true, dead_code : true,
conditionals: true, drop_debugger : true,
dead_code: true, conditionals : true,
drop_debugger: true, comparisons : true,
evaluate: true, evaluate : true,
hoist_funs: true, booleans : true,
hoist_vars: true, loops : true,
if_return: true, unused : true,
join_vars: true, hoist_funs : true,
keep_fargs: true, keep_fargs : true,
keep_fnames: false, keep_fnames : false,
loops: true, hoist_vars : true,
negate_iife: true, if_return : true,
properties: true, join_vars : true,
sequences: true, cascade : true,
side_effects: true, side_effects : true,
unused: true, negate_iife : true
} };
input: { input: {
// adapted from http://asmjs.org/spec/latest/ // adapted from http://asmjs.org/spec/latest/
function asm_GeometricMean(stdlib, foreign, buffer) { function asm_GeometricMean(stdlib, foreign, buffer) {
@@ -91,11 +91,12 @@ asm_mixed: {
function no_asm_GeometricMean(stdlib, foreign, buffer) { function no_asm_GeometricMean(stdlib, foreign, buffer) {
function logSum(start, end) { function logSum(start, end) {
start |= 0, end |= 0; start |= 0, end |= 0;
for (var sum = 0, p = 0, q = 0, p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]); var sum = 0, p = 0, q = 0;
for (p = start << 3, q = end << 3; (0 | p) < (0 | q); p = p + 8 | 0) sum += +log(values[p >> 3]);
return +sum; return +sum;
} }
function geometricMean(start, end) { function geometricMean(start, end) {
return start |= 0, end |= 0, +exp(logSum(start, end) / (end - start | 0)); return start |= 0, end |= 0, +exp(+logSum(start, end) / +(end - start | 0));
} }
var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer); var exp = stdlib.Math.exp, log = stdlib.Math.log, values = new stdlib.Float64Array(buffer);
return { geometricMean: geometricMean }; return { geometricMean: geometricMean };
@@ -103,131 +104,3 @@ asm_mixed: {
} }
} }
asm_toplevel: {
options = {}
input: {
"use asm";
0.0;
function f() {
0.0;
(function(){
0.0;
});
}
0.0;
}
expect_exact: '"use asm";0.0;function f(){0.0;(function(){0.0})}0.0;'
}
asm_function_expression: {
options = {}
input: {
0.0;
var a = function() {
"use asm";
0.0;
}
function f() {
0.0;
return function(){
"use asm";
0.0;
}
0.0;
}
0.0;
}
expect_exact: '0;var a=function(){"use asm";0.0};function f(){0;return function(){"use asm";0.0};0}0;'
}
asm_nested_functions: {
options = {}
input: {
0.0;
function a() {
"use asm";
0.0;
}
0.0;
function b() {
0.0;
function c(){
"use asm";
0.0;
}
0.0;
function d(){
0.0;
}
0.0;
}
0.0;
}
expect_exact: '0;function a(){"use asm";0.0}0;function b(){0;function c(){"use asm";0.0}0;function d(){0}0}0;'
}
issue_3636_1: {
mangle = {}
input: {
function n(stdlib, foreign, buffer) {
"use asm";
function add(x, y) {
x = x | 0;
y = y | 0;
return x + y | 0;
}
return {
add: add
};
}
console.log(new n().add("foo", 42));
}
expect: {
function n(o, e, u) {
"use asm";
function d(n, o) {
n = n | 0;
o = o | 0;
return n + o | 0;
}
return {
add: d
};
}
console.log(new n().add("foo", 42));
}
expect_stdout: "42"
}
issue_3636_2: {
mangle = {}
input: {
var n = function(stdlib, foreign, buffer) {
"use asm";
function add(x, y) {
x = x | 0;
y = y | 0;
return x + y | 0;
}
return {
add: add
};
};
console.log(new n().add("foo", 42));
}
expect: {
var n = function(n, o, e) {
"use asm";
function r(n, o) {
n = n | 0;
o = o | 0;
return n + o | 0;
}
return {
add: r
};
};
console.log(new n().add("foo", 42));
}
expect_stdout: "42"
}

View File

@@ -1,6 +1,5 @@
op_equals_left_local_var: { op_equals_left_local_var: {
options = { options = {
assignments: true,
evaluate: true, evaluate: true,
} }
input: { input: {
@@ -61,7 +60,6 @@ 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: {
@@ -125,7 +123,6 @@ 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: {
@@ -182,7 +179,6 @@ 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: {
@@ -240,224 +236,3 @@ 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_1: {
options = {
assignments: true,
reduce_vars: true,
}
input: {
function p(o) {
console.log(typeof o, o);
}
p(function(b) {
var a = b += 1;
--b;
return a;
}("object"));
}
expect: {
function p(o) {
console.log(typeof o, o);
}
p(function(b) {
var a = b += 1;
--b;
return a;
}("object"));
}
expect_stdout: "string object1"
}
issue_3375_2: {
options = {
assignments: true,
reduce_vars: true,
}
input: {
function p(o) {
console.log(typeof o, o);
}
p(function(b) {
var a = b -= 1;
--b;
return a;
}("object"));
}
expect: {
function p(o) {
console.log(typeof o, o);
}
p(function(b) {
var a = --b;
--b;
return a;
}("object"));
}
expect_stdout: "number NaN"
}
issue_3427: {
options = {
assignments: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
(function() {
var a;
a || (a = {});
})();
}
expect: {}
}
issue_3429_1: {
options = {
assignments: true,
side_effects: true,
unused: true,
}
input: {
var a = "PASS";
(function(b) {
b && (b = a = "FAIL");
})();
console.log(a);
}
expect: {
var a = "PASS";
(function(b) {
b = b && (a = "FAIL");
})();
console.log(a);
}
expect_stdout: "PASS"
}
issue_3429_2: {
options = {
assignments: true,
side_effects: true,
unused: true,
}
input: {
var a;
(function(b) {
b || (b = a = "FAIL");
})(42);
console.log(a);
}
expect: {
var a;
(function(b) {
b = b || (a = "FAIL");
})(42);
console.log(a);
}
expect_stdout: "undefined"
}
issue_3949_1: {
options = {
assignments: true,
evaluate: true,
reduce_vars: true,
}
input: {
var a = 42;
function f() {
var b = a;
b = b >> 2;
return 100 + b;
}
console.log(f());
}
expect: {
var a = 42;
function f() {
var b = a;
b >>= 2;
return 100 + b;
}
console.log(f());
}
expect_stdout: "110"
}
issue_3949_2: {
options = {
assignments: true,
evaluate: true,
reduce_vars: true,
}
input: {
var a = 42;
function f() {
var b = a;
b = 5 & b;
return 100 + b;
}
console.log(f());
}
expect: {
var a = 42;
function f() {
var b = a;
b &= 5;
return 100 + b;
}
console.log(f());
}
expect_stdout: "100"
}

View File

@@ -1,155 +0,0 @@
iife_boolean_context: {
options = {
booleans: true,
evaluate: true,
}
input: {
console.log(function() {
return Object(1) || false;
}() ? "PASS" : "FAIL");
console.log(function() {
return [].length || true;
}() ? "PASS" : "FAIL");
}
expect: {
console.log(function() {
return Object(1);
}() ? "PASS" : "FAIL");
console.log(function() {
return [].length, 1;
}() ? "PASS" : "FAIL");
}
expect_stdout: [
"PASS",
"PASS",
]
expect_warnings: [
"WARN: Dropping side-effect-free || [test/compress/booleans.js:2,19]",
"WARN: Boolean || always true [test/compress/booleans.js:5,19]",
]
}
issue_3465_1: {
options = {
booleans: true,
}
input: {
console.log(function(a) {
return typeof a;
}() ? "PASS" : "FAIL");
}
expect: {
console.log(function(a) {
return 1;
}() ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
issue_3465_2: {
options = {
booleans: true,
}
input: {
console.log(function f(a) {
if (!a) console.log(f(42));
return typeof a;
}() ? "PASS" : "FAIL");
}
expect: {
console.log(function f(a) {
if (!a) console.log(f(42));
return typeof a;
}() ? "PASS" : "FAIL");
}
expect_stdout: [
"number",
"PASS",
]
}
issue_3465_3: {
options = {
booleans: true,
passes: 2,
unused: true,
}
input: {
console.log(function f(a) {
return typeof a;
}() ? "PASS" : "FAIL");
}
expect: {
console.log(function(a) {
return 1;
}() ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
issue_2737_2: {
options = {
booleans: true,
inline: true,
reduce_vars: true,
unused: true,
}
input: {
(function(bar) {
for (;bar();) break;
})(function qux() {
return console.log("PASS"), qux;
});
}
expect: {
(function(bar) {
for (;bar();) break;
})(function() {
return console.log("PASS"), 1;
});
}
expect_stdout: "PASS"
}
issue_3658: {
options = {
booleans: true,
evaluate: true,
reduce_vars: true,
}
input: {
console.log(function f() {
console || f();
return "PASS";
}());
}
expect: {
console.log(function f() {
console || f();
return "PASS";
}());
}
expect_stdout: "PASS"
}
issue_3690: {
options = {
booleans: true,
unused: true,
}
input: {
console.log(function(a) {
return function() {
return a = [ this ];
}() ? "PASS" : "FAIL";
}());
}
expect: {
console.log(function(a) {
return function() {
return 1;
}() ? "PASS" : "FAIL";
}());
}
expect_stdout: "PASS"
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,76 @@
keep_comparisons: {
options = {
comparisons: true,
unsafe_comps: false
}
input: {
var obj1 = {
valueOf: function() {triggeredFirst();}
}
var obj2 = {
valueOf: function() {triggeredSecond();}
}
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
}
expect: {
var obj1 = {
valueOf: function() {triggeredFirst();}
}
var obj2 = {
valueOf: function() {triggeredSecond();}
}
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
}
}
keep_comparisons_with_unsafe_comps: {
options = {
comparisons: true,
unsafe_comps: true
}
input: {
var obj1 = {
valueOf: function() {triggeredFirst();}
}
var obj2 = {
valueOf: function() {triggeredSecond();}
}
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
}
expect: {
var obj1 = {
valueOf: function() {triggeredFirst();}
}
var obj2 = {
valueOf: function() {triggeredSecond();}
}
var result1 = obj2 >= obj1;
var result2 = obj2 > obj1;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
}
}
dont_change_in_or_instanceof_expressions: {
input: {
1 in 1;
null in null;
1 instanceof 1;
null instanceof null;
}
expect: {
1 in 1;
null in null;
1 instanceof 1;
null instanceof null;
}
}

View File

@@ -1,472 +0,0 @@
comparisons: {
options = {
comparisons: true,
}
input: {
var obj1, obj2;
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj1 >= obj2;
var result4 = obj1 > obj2;
}
expect: {
var obj1, obj2;
var result1 = obj1 <= obj2;
var result2 = obj1 < obj2;
var result3 = obj2 <= obj1;
var result4 = obj2 < obj1;
}
}
unsafe_comps: {
options = {
comparisons: true,
conditionals: true,
unsafe_comps: true,
}
input: {
var obj1, obj2;
obj1 <= obj2 ? f1() : g1();
obj1 < obj2 ? f2() : g2();
obj1 >= obj2 ? f3() : g3();
obj1 > obj2 ? f4() : g4();
}
expect: {
var obj1, obj2;
(obj2 < obj1 ? g1 : f1)();
(obj1 < obj2 ? f2 : g2)();
(obj1 < obj2 ? g3 : f3)();
(obj2 < obj1 ? f4 : g4)();
}
}
dont_change_in_or_instanceof_expressions: {
input: {
1 in 1;
null in null;
1 instanceof 1;
null instanceof null;
}
expect: {
1 in 1;
null in null;
1 instanceof 1;
null instanceof null;
}
}
self_comparison_1: {
options = {
comparisons: true,
}
input: {
a === a;
a !== b;
b.c === a.c;
b.c !== b.c;
}
expect: {
a == a;
a !== b;
b.c === a.c;
b.c != b.c;
}
}
self_comparison_2: {
options = {
comparisons: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
}
input: {
function f() {}
var o = {};
console.log(f != f, o === o);
}
expect: {
function f() {}
var o = {};
console.log(false, true);
}
expect_stdout: "false true"
}
self_comparison_3: {
options = {
comparisons: true,
}
input: {
var a;
function f() {
var b = a;
a = null;
return b;
}
for (var i = 0; i < 2; i++)
console.log(f() === f());
}
expect: {
var a;
function f() {
var b = a;
a = null;
return b;
}
for (var i = 0; i < 2; i++)
console.log(f() === f());
}
expect_stdout: [
"false",
"true",
]
}
issue_2857_1: {
options = {
comparisons: true,
}
input: {
function f1(a) {
a === undefined || a === null;
a === undefined || a !== null;
a !== undefined || a === null;
a !== undefined || a !== null;
a === undefined && a === null;
a === undefined && a !== null;
a !== undefined && a === null;
a !== undefined && a !== null;
}
function f2(a) {
a === null || a === undefined;
a === null || a !== undefined;
a !== null || a === undefined;
a !== null || a !== undefined;
a === null && a === undefined;
a === null && a !== undefined;
a !== null && a === undefined;
a !== null && a !== undefined;
}
}
expect: {
function f1(a) {
null == a;
void 0 === a || null !== a;
void 0 !== a || null === a;
void 0 !== a || null !== a;
void 0 === a && null === a;
void 0 === a && null !== a;
void 0 !== a && null === a;
null != a;
}
function f2(a) {
null == a;
null === a || void 0 !== a;
null !== a || void 0 === a;
null !== a || void 0 !== a;
null === a && void 0 === a;
null === a && void 0 !== a;
null !== a && void 0 === a;
null != a;
}
}
}
issue_2857_2: {
options = {
comparisons: true,
}
input: {
function f(a, p) {
a === undefined || a === null || p;
a === undefined || a !== null || p;
a !== undefined || a === null || p;
a !== undefined || a !== null || p;
a === undefined && a === null || p;
a === undefined && a !== null || p;
a !== undefined && a === null || p;
a !== undefined && a !== null || p;
}
}
expect: {
function f(a, p) {
null == a || p;
void 0 === a || null !== a || p;
void 0 !== a || null === a || p;
void 0 !== a || null !== a || p;
void 0 === a && null === a || p;
void 0 === a && null !== a || p;
void 0 !== a && null === a || p;
null != a || p;
}
}
}
issue_2857_3: {
options = {
comparisons: true,
}
input: {
function f(a, p) {
a === undefined || a === null && p;
a === undefined || a !== null && p;
a !== undefined || a === null && p;
a !== undefined || a !== null && p;
a === undefined && a === null && p;
a === undefined && a !== null && p;
a !== undefined && a === null && p;
a !== undefined && a !== null && p;
}
}
expect: {
function f(a, p) {
void 0 === a || null === a && p;
void 0 === a || null !== a && p;
void 0 !== a || null === a && p;
void 0 !== a || null !== a && p;
void 0 === a && null === a && p;
void 0 === a && null !== a && p;
void 0 !== a && null === a && p;
null != a && p;
}
}
}
issue_2857_4: {
options = {
comparisons: true,
}
input: {
function f(a, p) {
p || a === undefined || a === null;
p || a === undefined || a !== null;
p || a !== undefined || a === null;
p || a !== undefined || a !== null;
p || a === undefined && a === null;
p || a === undefined && a !== null;
p || a !== undefined && a === null;
p || a !== undefined && a !== null;
}
}
expect: {
function f(a, p) {
p || null == a;
p || void 0 === a || null !== a;
p || void 0 !== a || null === a;
p || void 0 !== a || null !== a;
p || void 0 === a && null === a;
p || void 0 === a && null !== a;
p || void 0 !== a && null === a;
p || null != a;
}
}
}
issue_2857_5: {
options = {
comparisons: true,
}
input: {
function f(a, p) {
p && a === undefined || a === null;
p && a === undefined || a !== null;
p && a !== undefined || a === null;
p && a !== undefined || a !== null;
p && a === undefined && a === null;
p && a === undefined && a !== null;
p && a !== undefined && a === null;
p && a !== undefined && a !== null;
}
}
expect: {
function f(a, p) {
p && void 0 === a || null === a;
p && void 0 === a || null !== a;
p && void 0 !== a || null === a;
p && void 0 !== a || null !== a;
p && void 0 === a && null === a;
p && void 0 === a && null !== a;
p && void 0 !== a && null === a;
p && null != a;
}
}
}
issue_2857_6: {
options = {
comparisons: true,
pure_getters: "strict",
reduce_vars: true,
}
input: {
function f(a) {
if (({}).b === undefined || {}.b === null)
return a.b !== undefined && a.b !== null;
}
console.log(f({
a: [ null ],
get b() {
return this.a.shift();
}
}));
}
expect: {
function f(a) {
if (null == {}.b)
return void 0 !== a.b && null !== a.b;
}
console.log(f({
a: [ null ],
get b() {
return this.a.shift();
}
}));
}
expect_stdout: "true"
}
is_boolean_unsafe: {
options = {
comparisons: true,
unsafe: true,
}
input: {
console.log(/foo/.test("bar") === [].isPrototypeOf({}));
}
expect: {
console.log(/foo/.test("bar") == [].isPrototypeOf({}));
}
expect_stdout: "true"
}
is_number_unsafe: {
options = {
comparisons: true,
unsafe: true,
}
input: {
console.log(Math.acos(42) !== "foo".charCodeAt(4));
}
expect: {
console.log(Math.acos(42) != "foo".charCodeAt(4));
}
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"
}

View File

@@ -1,7 +1,7 @@
concat_1: { concat_1: {
options = { options = {
evaluate: true, evaluate: true
} };
input: { input: {
var a = "foo" + "bar" + x() + "moo" + "foo" + y() + "x" + "y" + "z" + q(); var a = "foo" + "bar" + x() + "moo" + "foo" + y() + "x" + "y" + "z" + q();
var b = "foo" + 1 + x() + 2 + "boo"; var b = "foo" + 1 + x() + 2 + "boo";
@@ -21,14 +21,12 @@ concat_1: {
var c = 1 + x() + 2 + "boo"; var c = 1 + x() + 2 + "boo";
var d = 1 + x() + 2 + 3 + "boo"; var d = 1 + x() + 2 + 3 + "boo";
var e = 1 + x() + 2 + "X3boo"; var e = 1 + x() + 2 + "X3boo";
var f = "\x00360\x008\0"; var f = "\x00360\08\0";
} }
} }
concat_2: { concat_2: {
options = { options = {};
strings: true,
}
input: { input: {
console.log( console.log(
1 + (2 + 3), 1 + (2 + 3),
@@ -57,9 +55,7 @@ concat_2: {
} }
concat_3: { concat_3: {
options = { options = {};
strings: true,
}
input: { input: {
console.log( console.log(
1 + 2 + (3 + 4 + 5), 1 + 2 + (3 + 4 + 5),
@@ -88,9 +84,7 @@ concat_3: {
} }
concat_4: { concat_4: {
options = { options = {};
strings: true,
}
input: { input: {
console.log( console.log(
1 + "2" + (3 + 4 + 5), 1 + "2" + (3 + 4 + 5),
@@ -119,9 +113,7 @@ concat_4: {
} }
concat_5: { concat_5: {
options = { options = {};
strings: true,
}
input: { input: {
console.log( console.log(
"1" + 2 + (3 + 4 + 5), "1" + 2 + (3 + 4 + 5),
@@ -150,9 +142,7 @@ concat_5: {
} }
concat_6: { concat_6: {
options = { options = {};
strings: true,
}
input: { input: {
console.log( console.log(
"1" + "2" + (3 + 4 + 5), "1" + "2" + (3 + 4 + 5),
@@ -181,9 +171,6 @@ concat_6: {
} }
concat_7: { concat_7: {
options = {
strings: true,
}
input: { input: {
console.log( console.log(
"" + 1, "" + 1,
@@ -210,9 +197,6 @@ concat_7: {
} }
concat_8: { concat_8: {
options = {
strings: true,
}
input: { input: {
console.log( console.log(
1 + "", 1 + "",
@@ -237,20 +221,3 @@ concat_8: {
} }
expect_stdout: true expect_stdout: true
} }
issue_3689: {
options = {
strings: true,
}
input: {
console.log(function(a) {
return a + ("" + (a[0] = 0));
}([]));
}
expect: {
console.log(function(a) {
return a + ("" + (a[0] = 0));
}([]));
}
expect_stdout: "00"
}

File diff suppressed because it is too large Load Diff

166
test/compress/const.js Normal file
View File

@@ -0,0 +1,166 @@
issue_1191: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_vars : true,
}
input: {
function foo(rot) {
const rotTol = 5;
if (rot < -rotTol || rot > rotTol)
bar();
baz();
}
}
expect: {
function foo(rot) {
(rot < -5 || rot > 5) && bar();
baz();
}
}
}
issue_1194: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_vars : true,
}
input: {
function f1() {const a = "X"; return a + a;}
function f2() {const aa = "X"; return aa + aa;}
function f3() {const aaa = "X"; return aaa + aaa;}
}
expect: {
function f1(){return"XX"}
function f2(){return"XX"}
function f3(){return"XX"}
}
}
issue_1396: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_vars : true,
}
input: {
function foo(a) {
const VALUE = 1;
console.log(2 | VALUE);
console.log(VALUE + 1);
console.log(VALUE);
console.log(a & VALUE);
}
function bar() {
const s = "01234567890123456789";
console.log(s + s + s + s + s);
const CONSTANT = "abc";
console.log(CONSTANT + CONSTANT + CONSTANT + CONSTANT + CONSTANT);
}
}
expect: {
function foo(a) {
console.log(3);
console.log(2);
console.log(1);
console.log(1 & a);
}
function bar() {
const s = "01234567890123456789";
console.log(s + s + s + s + s);
console.log("abcabcabcabcabc");
}
}
}
unused_regexp_literal: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
}
input: {
function f(){ var a = /b/; }
}
expect: {
function f(){}
}
}
regexp_literal_not_const: {
options = {
evaluate : true,
booleans : true,
comparisons : true,
dead_code : true,
conditionals : true,
side_effects : true,
unused : true,
hoist_funs : true,
if_return : true,
join_vars : true,
sequences : false,
collapse_vars : false,
reduce_vars : true,
}
input: {
(function(){
var result;
const s = 'acdabcdeabbb';
const REGEXP_LITERAL = /ab*/g;
while (result = REGEXP_LITERAL.exec(s)) {
console.log(result[0]);
}
})();
}
expect: {
(function() {
var result;
const REGEXP_LITERAL = /ab*/g;
while (result = REGEXP_LITERAL.exec("acdabcdeabbb")) console.log(result[0]);
})();
}
expect_stdout: true
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
keep_debugger: { keep_debugger: {
options = { options = {
drop_debugger: false, drop_debugger: false
} };
input: { input: {
debugger; debugger;
} }
@@ -12,8 +12,8 @@ keep_debugger: {
drop_debugger: { drop_debugger: {
options = { options = {
drop_debugger: true, drop_debugger: true
} };
input: { input: {
debugger; debugger;
if (foo) debugger; if (foo) debugger;

View File

@@ -1,131 +0,0 @@
simple_statement_is_not_a_directive: {
input: {
"use strict"
.split(" ")
.forEach(function(s) {
console.log(s);
});
console.log(!this); // is strict mode?
(function() {
"directive"
""
"use strict"
"hello world"
.split(" ")
.forEach(function(s) {
console.log(s);
});
console.log(!this); // is strict mode?
})();
}
expect: {
"use strict".split(" ").forEach(function(s) {
console.log(s);
});
console.log(!this);
(function() {
"directive";
"";
"use strict";
"hello world".split(" ").forEach(function(s) {
console.log(s);
});
console.log(!this);
})();
}
expect_stdout: [
"use",
"strict",
"false",
"hello",
"world",
"true",
]
}
drop_lone_use_strict: {
options = {
directives: true,
unused: true,
}
input: {
function f1() {
"use strict";
}
function f2() {
"use strict";
function f3() {
"use strict";
}
}
(function f4() {
"use strict";
})();
}
expect: {
function f1() {
}
function f2() {
}
(function() {})();
}
}
issue_3166: {
options = {
directives: true,
}
input: {
"foo";
"use strict";
function f() {
"use strict";
"bar";
"use asm";
}
}
expect: {
"use strict";
function f() {
"use asm";
}
}
}
valid_after_invalid_1: {
input: {
console.log(typeof function() {
"use\x20strict";
"use strict";
return this;
}());
}
expect: {
console.log(typeof function() {
"use\x20strict";
"use strict";
return this;
}());
}
expect_stdout: "undefined"
}
valid_after_invalid_2: {
options = {
directives: true,
}
input: {
console.log(typeof function() {
"use\x20strict";
"use strict";
return this;
}());
}
expect: {
console.log(typeof function() {
"use strict";
return this;
}());
}
expect_stdout: "undefined"
}

View File

@@ -1,5 +1,5 @@
drop_console_1: { drop_console_1: {
options = {} options = {};
input: { input: {
console.log('foo'); console.log('foo');
console.log.apply(console, arguments); console.log.apply(console, arguments);
@@ -11,9 +11,7 @@ drop_console_1: {
} }
drop_console_2: { drop_console_2: {
options = { options = { drop_console: true };
drop_console: true,
}
input: { input: {
console.log('foo'); console.log('foo');
console.log.apply(console, arguments); console.log.apply(console, arguments);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,7 @@ must_replace: {
options = { options = {
global_defs: { global_defs: {
D: "foo bar", D: "foo bar",
}, }
} }
input: { input: {
console.log(D); console.log(D);
@@ -12,20 +12,6 @@ must_replace: {
} }
} }
repeated_nodes: {
options = {
global_defs: {
"@N": "rand()",
},
}
input: {
console.log(N, N);
}
expect: {
console.log(rand(), rand());
}
}
keyword: { keyword: {
options = { options = {
global_defs: { global_defs: {
@@ -51,7 +37,6 @@ object: {
VALUE: 42, VALUE: 42,
}, },
}, },
side_effects: true,
unsafe: true, unsafe: true,
} }
input: { input: {
@@ -135,7 +120,7 @@ mixed: {
properties: true, properties: true,
} }
input: { input: {
var FOO = { BAR: 0 }; const FOO = { BAR: 0 };
console.log(FOO.BAR); console.log(FOO.BAR);
console.log(++CONFIG.DEBUG); console.log(++CONFIG.DEBUG);
console.log(++CONFIG.VALUE); console.log(++CONFIG.VALUE);
@@ -145,7 +130,7 @@ mixed: {
console.log(CONFIG); console.log(CONFIG);
} }
expect: { expect: {
var FOO = { BAR: 0 }; const FOO = { BAR: 0 };
console.log("moo"); console.log("moo");
console.log(++CONFIG.DEBUG); console.log(++CONFIG.DEBUG);
console.log(++CONFIG.VALUE); console.log(++CONFIG.VALUE);
@@ -155,8 +140,9 @@ mixed: {
console.log(CONFIG); console.log(CONFIG);
} }
expect_warnings: [ expect_warnings: [
"WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:4,22]", 'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:126,22]',
"WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:7,8]", 'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:127,22]',
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:129,8]',
] ]
} }
@@ -174,59 +160,3 @@ issue_1801: {
console.log(!0); console.log(!0);
} }
} }
issue_1986: {
options = {
global_defs: {
"@alert": "console.log",
},
}
input: {
alert(42);
}
expect: {
console.log(42);
}
}
issue_2167: {
options = {
conditionals: true,
dead_code: true,
evaluate: true,
global_defs: {
"@isDevMode": "function(){}",
},
passes: 2,
side_effects: true,
}
input: {
if (isDevMode()) {
greetOverlord();
}
doWork();
}
expect: {
doWork();
}
}
issue_3217: {
options = {
collapse_vars: true,
global_defs: {
"@o": "{fn:function(){var a=42;console.log(a)}}",
},
inline: true,
properties: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
o.fn();
}
expect: {
console.log(42);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -88,24 +88,3 @@ sequences_funs: {
} }
} }
} }
issue_2295: {
options = {
collapse_vars: true,
hoist_vars: true,
}
input: {
function foo(o) {
var a = o.a;
if (a) return a;
var a = 1;
}
}
expect: {
function foo(o) {
var a = o.a;
if (a) return a;
a = 1;
}
}
}

View File

@@ -1,107 +1,55 @@
html_comment_in_expression: { html_comment_in_expression: {
input: { input: {
(function(a, b) { function f(a, b, x, y) { return a < !--b && x-- > y; }
console.log(a < !--b && a-- > b, a, b);
})(1, 2);
} }
expect_exact: "(function(a,b){console.log(a<! --b&&a-- >b,a,b)})(1,2);" expect_exact: "function f(a,b,x,y){return a< !--b&&x-- >y}";
expect_stdout: "false 1 1"
} }
html_comment_in_less_than: { html_comment_in_less_than: {
input: { input: {
(function(a, b, c) { function f(a, b) { return a < !--b; }
console.log(
a < !--b,
a < !--b + c,
a + b < !--c,
a, b, c
);
})(1, 2, 3);
} }
expect_exact: "(function(a,b,c){console.log(a<! --b,a<! --b+c,a+b<! --c,a,b,c)})(1,2,3);" expect_exact: "function f(a,b){return a< !--b}";
expect_stdout: "false true false 1 0 2"
} }
html_comment_in_left_shift: { html_comment_in_left_shift: {
input: { input: {
(function(a, b, c) { function f(a, b) { return a << !--b; }
console.log(
a << !--b,
a << !--b + c,
a + b << !--c,
a, b, c
);
})(1, 2, 3);
} }
expect_exact: "(function(a,b,c){console.log(a<<! --b,a<<! --b+c,a+b<<! --c,a,b,c)})(1,2,3);" expect_exact: "function f(a,b){return a<< !--b}";
expect_stdout: "1 16 1 1 0 2"
}
html_comment_in_greater_than: {
input: {
(function(a, b, c) {
console.log(
a-- > b,
a-- > b + c,
a + b-- > c,
a, b, c
);
})(1, 2, 3);
}
expect_exact: "(function(a,b,c){console.log(a-- >b,a-- >b+c,a+b-- >c,a,b,c)})(1,2,3);"
expect_stdout: "false false false -1 1 3"
}
html_comment_in_greater_than_or_equal: {
input: {
(function(a, b, c) {
console.log(
a-- >= b,
a-- >= b + c,
a + b-- >= c,
a, b, c
);
})(1, 2, 3);
}
expect_exact: "(function(a,b,c){console.log(a-- >=b,a-- >=b+c,a+b-- >=c,a,b,c)})(1,2,3);"
expect_stdout: "false false false -1 1 3"
} }
html_comment_in_right_shift: { html_comment_in_right_shift: {
input: { input: {
(function(a, b, c) { function f(a, b) { return a-- >> b; }
console.log(
a-- >> b,
a-- >> b + c,
a + b-- >> c,
a, b, c
);
})(1, 2, 3);
} }
expect_exact: "(function(a,b,c){console.log(a-- >>b,a-- >>b+c,a+b-- >>c,a,b,c)})(1,2,3);" expect_exact: "function f(a,b){return a-- >>b}";
expect_stdout: "0 0 0 -1 1 3"
} }
html_comment_in_zero_fill_right_shift: { html_comment_in_zero_fill_right_shift: {
input: { input: {
(function(a, b, c) { function f(a, b) { return a-- >>> b; }
console.log(
a-- >>> b,
a-- >>> b + c,
a + b-- >>> c,
a, b, c
);
})(1, 2, 3);
} }
expect_exact: "(function(a,b,c){console.log(a-- >>>b,a-- >>>b+c,a+b-- >>>c,a,b,c)})(1,2,3);" expect_exact: "function f(a,b){return a-- >>>b}";
expect_stdout: "0 0 0 -1 1 3" }
html_comment_in_greater_than: {
input: {
function f(a, b) { return a-- > b; }
}
expect_exact: "function f(a,b){return a-- >b}";
}
html_comment_in_greater_than_or_equal: {
input: {
function f(a, b) { return a-- >= b; }
}
expect_exact: "function f(a,b){return a-- >=b}";
} }
html_comment_in_string_literal: { html_comment_in_string_literal: {
input: { input: {
console.log("<!--HTML-->comment in<!--string literal-->".length); function f() { return "<!--HTML-->comment in<!--string literal-->"; }
} }
expect_exact: 'console.log("\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e".length);' expect_exact: 'function f(){return"\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e"}';
expect_stdout: "42"
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,14 @@
if_return_1: { if_return_1: {
options = { options = {
booleans: true, if_return : true,
comparisons: true, sequences : true,
conditionals: true, conditionals : true,
dead_code: true, comparisons : true,
evaluate: true, evaluate : true,
if_return: true, booleans : true,
sequences: true, unused : true,
side_effects: true, side_effects : true,
unused: true, dead_code : true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -24,15 +24,15 @@ if_return_1: {
if_return_2: { if_return_2: {
options = { options = {
booleans: true, if_return : true,
comparisons: true, sequences : true,
conditionals: true, conditionals : true,
dead_code: true, comparisons : true,
evaluate: true, evaluate : true,
if_return: true, booleans : true,
sequences: true, unused : true,
side_effects: true, side_effects : true,
unused: true, dead_code : true,
} }
input: { input: {
function f(x, y) { function f(x, y) {
@@ -49,15 +49,15 @@ if_return_2: {
if_return_3: { if_return_3: {
options = { options = {
booleans: true, if_return : true,
comparisons: true, sequences : true,
conditionals: true, conditionals : true,
dead_code: true, comparisons : true,
evaluate: true, evaluate : true,
if_return: true, booleans : true,
sequences: true, unused : true,
side_effects: true, side_effects : true,
unused: true, dead_code : true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -75,15 +75,15 @@ if_return_3: {
if_return_4: { if_return_4: {
options = { options = {
booleans: true, if_return : true,
comparisons: true, sequences : true,
conditionals: true, conditionals : true,
dead_code: true, comparisons : true,
evaluate: true, evaluate : true,
if_return: true, booleans : true,
sequences: true, unused : true,
side_effects: true, side_effects : true,
unused: true, dead_code : true,
} }
input: { input: {
function f(x, y) { function f(x, y) {
@@ -100,15 +100,15 @@ if_return_4: {
if_return_5: { if_return_5: {
options = { options = {
booleans: true, if_return : true,
comparisons: true, sequences : true,
conditionals: true, conditionals : true,
dead_code: true, comparisons : true,
evaluate: true, evaluate : true,
if_return: true, booleans : true,
sequences: true, unused : true,
side_effects: true, side_effects : true,
unused: true, dead_code : true,
} }
input: { input: {
function f() { function f() {
@@ -126,15 +126,15 @@ if_return_5: {
if_return_6: { if_return_6: {
options = { options = {
booleans: true, if_return : true,
comparisons: true, sequences : true,
conditionals: true, conditionals : true,
dead_code: true, comparisons : true,
evaluate: true, evaluate : true,
if_return: true, booleans : true,
sequences: true, unused : true,
side_effects: true, side_effects : true,
unused: true, dead_code : true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -150,15 +150,15 @@ if_return_6: {
if_return_7: { if_return_7: {
options = { options = {
booleans: true, if_return : true,
comparisons: true, sequences : true,
conditionals: true, conditionals : true,
dead_code: true, comparisons : true,
evaluate: true, evaluate : true,
if_return: true, booleans : true,
sequences: true, unused : true,
side_effects: true, side_effects : true,
unused: true, dead_code : true,
} }
input: { input: {
function f(x) { function f(x) {
@@ -176,10 +176,10 @@ if_return_7: {
if_return_8: { if_return_8: {
options = { options = {
conditionals: true, if_return: true,
if_return: true, sequences: true,
sequences: true, conditionals: true,
side_effects: true, side_effects : true,
} }
input: { input: {
function f(e) { function f(e) {
@@ -220,15 +220,15 @@ if_return_8: {
issue_1089: { issue_1089: {
options = { options = {
booleans: true, if_return : true,
comparisons: true, sequences : true,
conditionals: true, conditionals : true,
dead_code: true, comparisons : true,
evaluate: true, evaluate : true,
if_return: true, booleans : true,
sequences: true, unused : true,
side_effects: true, side_effects : true,
unused: true, dead_code : true,
} }
input: { input: {
function x() { function x() {
@@ -243,7 +243,7 @@ issue_1089: {
expect: { expect: {
function x() { function x() {
var f = document.getElementById("fname"); var f = document.getElementById("fname");
if (12345 < f.files[0].size) if (f.files[0].size > 12345)
return alert("alert"), f.focus(), !1; return alert("alert"), f.focus(), !1;
} }
} }
@@ -251,9 +251,9 @@ issue_1089: {
issue_1437: { issue_1437: {
options = { options = {
conditionals: false, if_return : true,
if_return: true, sequences : true,
sequences: true, conditionals : false
} }
input: { input: {
function x() { function x() {
@@ -281,9 +281,9 @@ issue_1437: {
issue_1437_conditionals: { issue_1437_conditionals: {
options = { options = {
conditionals: true, conditionals : true,
if_return: true, if_return : true,
sequences: true, sequences : true
} }
input: { input: {
function x() { function x() {
@@ -302,295 +302,3 @@ issue_1437_conditionals: {
} }
} }
} }
issue_512: {
options = {
conditionals: true,
if_return: true,
sequences: true,
side_effects: true,
}
input: {
function a() {
if (b()) {
c();
return;
}
throw e;
}
}
expect: {
function a() {
if (!b()) throw e;
c();
}
}
}
if_var_return: {
options = {
conditionals: true,
if_return: true,
join_vars: true,
sequences: true,
}
input: {
function f() {
var a;
return;
var b;
}
function g() {
var a;
if (u()) {
var b;
return v();
var c;
}
var d;
if (w()) {
var e;
return x();
var f;
} else {
var g;
y();
var h;
}
var i;
z();
var j;
}
}
expect: {
function f() {
var a, b;
}
function g() {
var a, b, c, d, e, f, g, h, i, j;
return u() ? v() : w() ? x() : (y(), z(), void 0);
}
}
}
if_if_return_return: {
options = {
conditionals: true,
if_return: true,
}
input: {
function f(a, b) {
if (a) {
if (b)
return b;
return;
}
g();
}
}
expect: {
function f(a, b) {
if (a)
return b || void 0;
g();
}
}
}
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",
]
}
issue_3600: {
options = {
if_return: true,
inline: true,
side_effects: true,
unused: true,
}
input: {
var c = 0;
(function() {
if ([ ][c++]); else return;
return void function() {
var b = --b, a = c = 42;
return c;
}();
})();
console.log(c);
}
expect: {
var c = 0;
(function() {
if ([][c++]) b = --b, c = 42;
var b;
})();
console.log(c);
}
expect_stdout: "1"
}
iife_if_return_simple: {
options = {
conditionals: true,
if_return: true,
inline: true,
sequences: true,
side_effects: true,
}
input: {
(function() {
if (console)
return console.log("PASS");
console.log("FAIL");
})();
}
expect: {
console ? console.log("PASS") : console.log("FAIL");
}
expect_stdout: "PASS"
}

View File

@@ -1,17 +1,8 @@
non_hoisted_function_after_return: { non_hoisted_function_after_return: {
options = { options = {
booleans: true, hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
comparisons: true, evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
conditionals: true, if_return: true, join_vars: true, cascade: true, side_effects: true
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
} }
input: { input: {
function foo(x) { function foo(x) {
@@ -30,35 +21,25 @@ non_hoisted_function_after_return: {
} }
expect: { expect: {
function foo(x) { function foo(x) {
return (x ? bar : baz)(); return x ? bar() : baz();
function bar() { return 7 } function bar() { return 7 }
function baz() { return 8 } function baz() { return 8 }
} }
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]", 'WARN: Dropping unreachable code [test/compress/issue-1034.js:11,16]',
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:14,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:17,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:11,21]" "WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:18,21]"
] ]
} }
non_hoisted_function_after_return_2a: { non_hoisted_function_after_return_2a: {
options = { options = {
booleans: true, hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
collapse_vars: false, evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
comparisons: true, if_return: true, join_vars: true, cascade: true, side_effects: true,
conditionals: true, collapse_vars: false, passes: 2, warnings: "verbose"
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
passes: 2,
side_effects: true,
unused: true,
} }
input: { input: {
function foo(x) { function foo(x) {
@@ -84,37 +65,26 @@ non_hoisted_function_after_return_2a: {
} }
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:48,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:4,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:48,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:51,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:4,20]", "WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]", "WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]",
"INFO: pass 0: last_count: Infinity, count: 36", "WARN: Dropping unreachable code [test/compress/issue-1034.js:53,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]", "WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]",
"INFO: Dropping unused variable b [test/compress/issue-1034.js:7,20]", "WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
"INFO: pass 1: last_count: 36, count: 18",
] ]
} }
non_hoisted_function_after_return_2b: { non_hoisted_function_after_return_2b: {
options = { options = {
booleans: true, hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
collapse_vars: false, evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
comparisons: true, if_return: true, join_vars: true, cascade: true, side_effects: true,
conditionals: true, collapse_vars: false
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
} }
input: { input: {
function foo(x) { function foo(x) {
@@ -138,173 +108,11 @@ non_hoisted_function_after_return_2b: {
} }
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:6,16]", // duplicate warnings no longer emitted
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:6,16]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:95,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:95,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,12]", "WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,12]", "WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,12]",
] "WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]",
}
non_hoisted_function_after_return_strict: {
options = {
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
}
input: {
"use strict";
function foo(x) {
if (x) {
return bar();
not_called1();
} else {
return baz();
not_called2();
}
function bar() { return 7; }
return not_reached;
function UnusedFunction() {}
function baz() { return 8; }
}
console.log(foo(0), foo(1));
}
expect: {
"use strict";
function foo(x) {
return (x ? bar : baz)();
function bar() { return 7 }
function baz() { return 8 }
}
console.log(foo(0), foo(1));
}
expect_stdout: "8 7"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:5,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:11,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:12,21]",
]
}
non_hoisted_function_after_return_2a_strict: {
options = {
booleans: true,
collapse_vars: false,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
passes: 2,
side_effects: true,
unused: true,
}
input: {
"use strict";
function foo(x) {
if (x) {
return bar(1);
var a = not_called(1);
} else {
return bar(2);
var b = not_called(2);
}
var c = bar(3);
function bar(x) { return 7 - x; }
function nope() {}
return b || c;
}
console.log(foo(0), foo(1));
}
expect: {
"use strict";
function foo(x) {
return bar(x ? 1 : 2);
function bar(x) {
return 7 - x;
}
}
console.log(foo(0), foo(1));
}
expect_stdout: "5 6"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:5,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:5,16]",
"WARN: Dropping 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 function nope [test/compress/issue-1034.js:12,21]",
"INFO: pass 0: last_count: Infinity, count: 47",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
"INFO: Dropping unused variable b [test/compress/issue-1034.js:8,20]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:10,16]",
"INFO: pass 1: last_count: 47, count: 29",
]
}
non_hoisted_function_after_return_2b_strict: {
options = {
booleans: true,
collapse_vars: false,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: false,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
side_effects: true,
unused: true,
}
input: {
"use strict";
function foo(x) {
if (x) {
return bar(1);
} else {
return bar(2);
var b;
}
var c = bar(3);
function bar(x) {
return 7 - x;
}
return b || c;
}
console.log(foo(0), foo(1));
}
expect: {
"use strict";
function foo(x) {
return bar(x ? 1 : 2);
function bar(x) { return 7 - x; }
}
console.log(foo(0), foo(1));
}
expect_stdout: "5 6"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:9,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:9,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:13,12]",
] ]
} }

View File

@@ -1,9 +1,21 @@
const_declaration: {
options = {
evaluate: true
};
input: {
const goog = goog || {};
}
expect: {
const goog = goog || {};
}
}
const_pragma: { const_pragma: {
options = { options = {
evaluate: true, evaluate: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
} };
input: { input: {
/** @const */ var goog = goog || {}; /** @const */ var goog = goog || {};
@@ -17,9 +29,8 @@ const_pragma: {
not_const: { not_const: {
options = { options = {
evaluate: true, evaluate: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
} };
input: { input: {
var goog = goog || {}; var goog = goog || {};

View File

@@ -1,91 +1,90 @@
multiple_functions: { multiple_functions: {
options = { options = { if_return: true, hoist_funs: false };
hoist_funs: false,
if_return: true,
}
input: { input: {
( function() { ( function() {
if ( !window ) { if ( !window ) {
return; return;
} }
function f() {} function f() {}
function g() {} function g() {}
} )(); } )();
} }
expect: { expect: {
( function() { ( function() {
function f() {}
function g() {}
// NOTE: other compression steps will reduce this // NOTE: other compression steps will reduce this
// down to just `window`. // down to just `window`.
if ( window ); if ( window );
function f() {}
function g() {}
} )(); } )();
} }
} }
single_function: { single_function: {
options = { options = { if_return: true, hoist_funs: false };
hoist_funs: false,
if_return: true,
}
input: { input: {
( function() { ( function() {
if ( !window ) { if ( !window ) {
return; return;
} }
function f() {} function f() {}
} )(); } )();
} }
expect: { expect: {
( function() { ( function() {
if ( window );
function f() {} function f() {}
if ( window );
} )(); } )();
} }
} }
deeply_nested: { deeply_nested: {
options = { options = { if_return: true, hoist_funs: false };
hoist_funs: false,
if_return: true,
}
input: { input: {
( function() { ( function() {
if ( !window ) { if ( !window ) {
return; return;
} }
function f() {} function f() {}
function g() {} function g() {}
if ( !document ) { if ( !document ) {
return; return;
} }
function h() {} function h() {}
} )(); } )();
} }
expect: { expect: {
( function() { ( function() {
function f() {}
function g() {}
function h() {}
// NOTE: other compression steps will reduce this // NOTE: other compression steps will reduce this
// down to just `window`. // down to just `window`.
if ( window ) if ( window )
if (document); if (document);
function f() {}
function g() {}
function h() {}
} )(); } )();
} }
} }
not_hoisted_when_already_nested: { not_hoisted_when_already_nested: {
options = { options = { if_return: true, hoist_funs: false };
hoist_funs: false,
if_return: true,
}
input: { input: {
( function() { ( function() {
if ( !window ) { if ( !window ) {
return; return;
} }
if ( foo ) function f() {} if ( foo ) function f() {}
} )(); } )();
} }
expect: { expect: {
@@ -95,70 +94,3 @@ not_hoisted_when_already_nested: {
} )(); } )();
} }
} }
defun_if_return: {
options = {
hoist_funs: false,
if_return: true,
}
input: {
function e() {
function f() {}
if (!window) return;
else function g() {}
function h() {}
}
}
expect: {
function e() {
function f() {}
if (window) function g() {}
function h() {}
}
}
}
defun_hoist_funs: {
options = {
hoist_funs: true,
if_return: true,
}
input: {
function e() {
function f() {}
if (!window) return;
else function g() {}
function h() {}
}
}
expect: {
function e() {
function f() {}
function g() {}
function h() {}
if (window);
}
}
}
defun_else_if_return: {
options = {
hoist_funs: false,
if_return: true,
}
input: {
function e() {
function f() {}
if (window) function g() {}
else return;
function h() {}
}
}
expect: {
function e() {
function f() {}
if (window) function g() {}
function h() {}
}
}
}

View File

@@ -1,6 +1,6 @@
with_in_global_scope: { with_in_global_scope: {
options = { options = {
unused: true, unused: true
} }
input: { input: {
var o = 42; var o = 42;
@@ -18,7 +18,7 @@ with_in_global_scope: {
} }
with_in_function_scope: { with_in_function_scope: {
options = { options = {
unused: true, unused: true
} }
input: { input: {
function foo() { function foo() {
@@ -40,7 +40,7 @@ with_in_function_scope: {
} }
compress_with_with_in_other_scope: { compress_with_with_in_other_scope: {
options = { options = {
unused: true, unused: true
} }
input: { input: {
function foo() { function foo() {
@@ -69,7 +69,7 @@ compress_with_with_in_other_scope: {
} }
with_using_existing_variable_outside_scope: { with_using_existing_variable_outside_scope: {
options = { options = {
unused: true, unused: true
} }
input: { input: {
function f() { function f() {
@@ -99,7 +99,7 @@ with_using_existing_variable_outside_scope: {
} }
check_drop_unused_in_peer_function: { check_drop_unused_in_peer_function: {
options = { options = {
unused: true, unused: true
} }
input: { input: {
function outer() { function outer() {
@@ -148,7 +148,7 @@ check_drop_unused_in_peer_function: {
Infinity_not_in_with_scope: { Infinity_not_in_with_scope: {
options = { options = {
unused: true, unused: true
} }
input: { input: {
var o = { Infinity: 'oInfinity' }; var o = { Infinity: 'oInfinity' };
@@ -164,7 +164,7 @@ Infinity_not_in_with_scope: {
Infinity_in_with_scope: { Infinity_in_with_scope: {
options = { options = {
unused: true, unused: true
} }
input: { input: {
var o = { Infinity: 'oInfinity' }; var o = { Infinity: 'oInfinity' };
@@ -180,19 +180,20 @@ Infinity_in_with_scope: {
assorted_Infinity_NaN_undefined_in_with_scope: { assorted_Infinity_NaN_undefined_in_with_scope: {
options = { options = {
booleans: true, unused: true,
comparisons: true, evaluate: true,
conditionals: true, dead_code: true,
dead_code: true, conditionals: true,
evaluate: true, comparisons: true,
hoist_funs: true, booleans: true,
if_return: true, hoist_funs: true,
join_vars: true, keep_fargs: true,
keep_fargs: true, if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
sequences: false,
keep_infinity: false, keep_infinity: false,
sequences: false,
side_effects: true,
unused: true,
} }
input: { input: {
var f = console.log; var f = console.log;
@@ -242,19 +243,20 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
assorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: { assorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: {
options = { options = {
booleans: true, unused: true,
comparisons: true, evaluate: true,
conditionals: true, dead_code: true,
dead_code: true, conditionals: true,
evaluate: true, comparisons: true,
hoist_funs: true, booleans: true,
if_return: true, hoist_funs: true,
join_vars: true, keep_fargs: true,
keep_fargs: true, if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
sequences: false,
keep_infinity: true, keep_infinity: true,
sequences: false,
side_effects: true,
unused: true,
} }
input: { input: {
var f = console.log; var f = console.log;

View File

@@ -1,15 +1,11 @@
keep_name_of_getter: { keep_name_of_getter: {
options = { options = { unused: true };
unused: true,
}
input: { a = { get foo () {} } } input: { a = { get foo () {} } }
expect: { a = { get foo () {} } } expect: { a = { get foo () {} } }
} }
keep_name_of_setter: { keep_name_of_setter: {
options = { options = { unused: true };
unused: true,
}
input: { a = { set foo () {} } } input: { a = { set foo () {} } }
expect: { a = { set foo () {} } } expect: { a = { set foo () {} } }
} }

View File

@@ -1,7 +1,7 @@
mangle_keep_fnames_false: { mangle_keep_fnames_false: {
options = { options = {
keep_fargs: true, keep_fnames : true,
keep_fnames: true, keep_fargs : true,
} }
mangle = { mangle = {
keep_fnames : false, keep_fnames : false,
@@ -26,8 +26,8 @@ mangle_keep_fnames_false: {
mangle_keep_fnames_true: { mangle_keep_fnames_true: {
options = { options = {
keep_fargs: true, keep_fnames : true,
keep_fnames: true, keep_fargs : true,
} }
mangle = { mangle = {
keep_fnames : true, keep_fnames : true,

View File

@@ -1,14 +1,15 @@
pure_function_calls: { pure_function_calls: {
options = { options = {
booleans: true, evaluate : true,
comparisons: true, conditionals : true,
conditionals: true, comparisons : true,
evaluate: true, side_effects : true,
if_return: true, booleans : true,
join_vars: true, unused : true,
negate_iife: true, if_return : true,
side_effects: true, join_vars : true,
unused: true, cascade : true,
negate_iife : true,
} }
input: { input: {
// pure top-level IIFE will be dropped // pure top-level IIFE will be dropped
@@ -48,28 +49,29 @@ pure_function_calls: {
a.b(), f.g(); a.b(), f.g();
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:3,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:17,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:3,8]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:17,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,37]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:30,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:16,16]", "WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:30,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:14,8]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:28,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:24,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:38,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:25,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:39,31]",
] ]
} }
pure_function_calls_toplevel: { pure_function_calls_toplevel: {
options = { options = {
booleans: true, evaluate : true,
comparisons: true, conditionals : true,
conditionals: true, comparisons : true,
evaluate: true, side_effects : true,
if_return: true, booleans : true,
join_vars: true, unused : true,
negate_iife: true, if_return : true,
side_effects: true, join_vars : true,
toplevel: true, cascade : true,
unused: true, negate_iife : true,
toplevel : true,
} }
input: { input: {
// pure top-level IIFE will be dropped // pure top-level IIFE will be dropped
@@ -94,13 +96,6 @@ pure_function_calls_toplevel: {
})(); })();
})(); })();
// pure top-level calls will be dropped regardless of the leading comments position
var MyClass = /*#__PURE__*//*@class*/(function(){
function MyClass() {}
MyClass.prototype.method = function() {};
return MyClass;
})();
// comment #__PURE__ comment // comment #__PURE__ comment
bar(), baz(), quux(); bar(), baz(), quux();
a.b(), /* @__PURE__ */ c.d.e(), f.g(); a.b(), /* @__PURE__ */ c.d.e(), f.g();
@@ -110,17 +105,15 @@ pure_function_calls_toplevel: {
a.b(), f.g(); a.b(), f.g();
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:3,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:79,8]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:3,8]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:79,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:16,37]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:92,37]",
"WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:16,16]", "WARN: Dropping unused variable iife2 [test/compress/issue-1261.js:92,16]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:14,8]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:90,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:31,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:100,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:32,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:101,31]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:8,33]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:84,33]",
"WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:8,12]", "WARN: Dropping unused variable iife1 [test/compress/issue-1261.js:84,12]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:24,45]",
"WARN: Dropping unused variable MyClass [test/compress/issue-1261.js:24,12]",
] ]
} }
@@ -155,29 +148,29 @@ should_warn: {
baz(); baz();
} }
expect_warnings: [ expect_warnings: [
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:1,61]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,61]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:1,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:128,23]",
"WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:1,23]", "WARN: Dropping side-effect-free statement [test/compress/issue-1261.js:128,23]",
"WARN: Boolean || always true [test/compress/issue-1261.js:2,23]", "WARN: Boolean || always true [test/compress/issue-1261.js:129,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:2,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:129,23]",
"WARN: Condition always true [test/compress/issue-1261.js:2,23]", "WARN: Condition always true [test/compress/issue-1261.js:129,23]",
"WARN: Condition left of || always true [test/compress/issue-1261.js:3,8]", "WARN: Condition left of || always true [test/compress/issue-1261.js:130,8]",
"WARN: Condition always true [test/compress/issue-1261.js:3,8]", "WARN: Condition always true [test/compress/issue-1261.js:130,8]",
"WARN: Boolean && always false [test/compress/issue-1261.js:4,23]", "WARN: Boolean && always false [test/compress/issue-1261.js:131,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:4,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:131,23]",
"WARN: Condition always false [test/compress/issue-1261.js:4,23]", "WARN: Condition always false [test/compress/issue-1261.js:131,23]",
"WARN: Condition left of && always false [test/compress/issue-1261.js:5,8]", "WARN: Condition left of && always false [test/compress/issue-1261.js:132,8]",
"WARN: Condition always false [test/compress/issue-1261.js:5,8]", "WARN: Condition always false [test/compress/issue-1261.js:132,8]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:6,23]", "WARN: + in boolean context always true [test/compress/issue-1261.js:133,23]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:6,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:133,23]",
"WARN: Condition always true [test/compress/issue-1261.js:6,23]", "WARN: Condition always true [test/compress/issue-1261.js:133,23]",
"WARN: + in boolean context always true [test/compress/issue-1261.js:7,8]", "WARN: + in boolean context always true [test/compress/issue-1261.js:134,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:7,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:134,31]",
"WARN: Condition always true [test/compress/issue-1261.js:7,8]", "WARN: Condition always true [test/compress/issue-1261.js:134,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:8,23]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:135,23]",
"WARN: Condition always true [test/compress/issue-1261.js:9,8]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:136,24]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:9,24]", "WARN: Condition always true [test/compress/issue-1261.js:136,8]",
"WARN: Dropping __PURE__ call [test/compress/issue-1261.js:10,31]", "WARN: Dropping __PURE__ call [test/compress/issue-1261.js:137,31]",
"WARN: Condition always false [test/compress/issue-1261.js:10,8]", "WARN: Condition always false [test/compress/issue-1261.js:137,8]",
] ]
} }

View File

@@ -1,16 +1,17 @@
string_plus_optimization: { string_plus_optimization: {
options = { options = {
booleans: true, side_effects : true,
comparisons: true, evaluate : true,
conditionals: true, conditionals : true,
dead_code: true, comparisons : true,
evaluate: true, dead_code : true,
hoist_funs: true, booleans : true,
if_return: true, unused : true,
join_vars: true, if_return : true,
side_effects: true, join_vars : true,
unused: true, cascade : true,
} hoist_funs : true,
};
input: { input: {
function foo(anything) { function foo(anything) {
function throwing_function() { function throwing_function() {

View File

@@ -1,8 +1,6 @@
issue_1321_no_debug: { issue_1321_no_debug: {
mangle = { mangle_props = {
properties: { ignore_quoted: true
keep_quoted: true,
},
} }
input: { input: {
var x = {}; var x = {};
@@ -12,19 +10,17 @@ issue_1321_no_debug: {
} }
expect: { expect: {
var x = {}; var x = {};
x.x = 1; x.b = 1;
x["a"] = 2 * x.x; x["a"] = 2 * x.b;
console.log(x.x, x["a"]); console.log(x.b, x["a"]);
} }
expect_stdout: true expect_stdout: true
} }
issue_1321_debug: { issue_1321_debug: {
mangle = { mangle_props = {
properties: { ignore_quoted: true,
debug: "", debug: ""
keep_quoted: true,
},
} }
input: { input: {
var x = {}; var x = {};
@@ -34,18 +30,16 @@ issue_1321_debug: {
} }
expect: { expect: {
var x = {}; var x = {};
x.x = 1; x.a = 1;
x["_$foo$_"] = 2 * x.x; x["_$foo$_"] = 2 * x.a;
console.log(x.x, x["_$foo$_"]); console.log(x.a, x["_$foo$_"]);
} }
expect_stdout: true expect_stdout: true
} }
issue_1321_with_quoted: { issue_1321_with_quoted: {
mangle = { mangle_props = {
properties: { ignore_quoted: false
keep_quoted: false,
},
} }
input: { input: {
var x = {}; var x = {};
@@ -55,9 +49,9 @@ issue_1321_with_quoted: {
} }
expect: { expect: {
var x = {}; var x = {};
x.x = 1; x.a = 1;
x["o"] = 2 * x.x; x["b"] = 2 * x.a;
console.log(x.x, x["o"]); console.log(x.a, x["b"]);
} }
expect_stdout: true expect_stdout: true
} }

View File

@@ -15,7 +15,7 @@
tranformation_sort_order_equal: { tranformation_sort_order_equal: {
options = { options = {
comparisons: true, comparisons: true,
} };
input: { (a = parseInt('100')) == a } input: { (a = parseInt('100')) == a }
expect: { (a = parseInt('100')) == a } expect: { (a = parseInt('100')) == a }
@@ -24,7 +24,7 @@ tranformation_sort_order_equal: {
tranformation_sort_order_unequal: { tranformation_sort_order_unequal: {
options = { options = {
comparisons: true, comparisons: true,
} };
input: { (a = parseInt('100')) != a } input: { (a = parseInt('100')) != a }
expect: { (a = parseInt('100')) != a } expect: { (a = parseInt('100')) != a }
@@ -33,7 +33,7 @@ tranformation_sort_order_unequal: {
tranformation_sort_order_lesser_or_equal: { tranformation_sort_order_lesser_or_equal: {
options = { options = {
comparisons: true, comparisons: true,
} };
input: { (a = parseInt('100')) <= a } input: { (a = parseInt('100')) <= a }
expect: { (a = parseInt('100')) <= a } expect: { (a = parseInt('100')) <= a }
@@ -41,7 +41,7 @@ tranformation_sort_order_lesser_or_equal: {
tranformation_sort_order_greater_or_equal: { tranformation_sort_order_greater_or_equal: {
options = { options = {
comparisons: true, comparisons: true,
} };
input: { (a = parseInt('100')) >= a } input: { (a = parseInt('100')) >= a }
expect: { (a = parseInt('100')) >= a } expect: { (a = parseInt('100')) >= a }

View File

@@ -1,6 +1,6 @@
level_zero: { level_zero: {
options = { options = {
keep_fnames: true, keep_fnames: true
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true
@@ -29,7 +29,7 @@ level_zero: {
level_one: { level_one: {
options = { options = {
keep_fnames: true, keep_fnames: true
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true
@@ -58,7 +58,7 @@ level_one: {
level_two: { level_two: {
options = { options = {
keep_fnames: true, keep_fnames: true
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true
@@ -97,7 +97,7 @@ level_two: {
level_three: { level_three: {
options = { options = {
keep_fnames: true, keep_fnames: true
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true

View File

@@ -4,7 +4,7 @@ unsafe_undefined: {
options = { options = {
conditionals: true, conditionals: true,
if_return: true, if_return: true,
unsafe_undefined: true, unsafe: true
} }
mangle = {} mangle = {}
input: { input: {
@@ -30,7 +30,7 @@ keep_fnames: {
options = { options = {
conditionals: true, conditionals: true,
if_return: true, if_return: true,
unsafe_undefined: true, unsafe: true
} }
mangle = { mangle = {
keep_fnames: true keep_fnames: true

View File

@@ -1,7 +1,6 @@
typeof_eq_undefined: { typeof_eq_undefined: {
options = { options = {
comparisons: true, comparisons: true
typeofs: true,
} }
input: { input: {
var a = typeof b != "undefined"; var a = typeof b != "undefined";
@@ -24,8 +23,7 @@ typeof_eq_undefined: {
typeof_eq_undefined_ie8: { typeof_eq_undefined_ie8: {
options = { options = {
comparisons: true, comparisons: true,
ie8: true, screw_ie8: false
typeofs: true,
} }
input: { input: {
var a = typeof b != "undefined"; var a = typeof b != "undefined";
@@ -47,8 +45,7 @@ typeof_eq_undefined_ie8: {
undefined_redefined: { undefined_redefined: {
options = { options = {
comparisons: true, comparisons: true
typeofs: true,
} }
input: { input: {
function f(undefined) { function f(undefined) {
@@ -61,8 +58,7 @@ undefined_redefined: {
undefined_redefined_mangle: { undefined_redefined_mangle: {
options = { options = {
comparisons: true, comparisons: true
typeofs: true,
} }
mangle = {} mangle = {}
input: { input: {

View File

@@ -22,17 +22,18 @@ else_with_empty_statement: {
conditional_false_stray_else_in_loop: { conditional_false_stray_else_in_loop: {
options = { options = {
booleans: true, evaluate : true,
comparisons: true, comparisons : true,
conditionals: false, booleans : true,
dead_code: true, unused : true,
evaluate: true, loops : true,
hoist_vars: true, side_effects : true,
if_return: true, dead_code : true,
join_vars: true, hoist_vars : true,
loops: true, join_vars : true,
side_effects: true, if_return : true,
unused: true, cascade : true,
conditionals : false,
} }
input: { input: {
for (var i = 1; i <= 4; ++i) { for (var i = 1; i <= 4; ++i) {

View File

@@ -1,9 +1,9 @@
screw_ie8: { screw_ie8: {
options = { options = {
ie8: false, screw_ie8: true,
} }
mangle = { mangle = {
ie8: false, screw_ie8: true,
} }
input: { input: {
try { throw "foo"; } catch (x) { console.log(x); } try { throw "foo"; } catch (x) { console.log(x); }
@@ -16,10 +16,10 @@ screw_ie8: {
support_ie8: { support_ie8: {
options = { options = {
ie8: true, screw_ie8: false,
} }
mangle = { mangle = {
ie8: true, screw_ie8: false,
} }
input: { input: {
try { throw "foo"; } catch (x) { console.log(x); } try { throw "foo"; } catch (x) { console.log(x); }
@@ -61,7 +61,7 @@ unsafe_undefined: {
options = { options = {
conditionals: true, conditionals: true,
if_return: true, if_return: true,
unsafe_undefined: true, unsafe: true,
} }
mangle = {} mangle = {}
input: { input: {
@@ -85,3 +85,15 @@ unsafe_undefined: {
} }
expect_stdout: true expect_stdout: true
} }
runtime_error: {
input: {
const a = 1;
console.log(a++);
}
expect: {
const a = 1;
console.log(a++);
}
expect_stdout: true
}

View File

@@ -2,7 +2,6 @@ chained_evaluation_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,
evaluate: true, evaluate: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -19,7 +18,9 @@ chained_evaluation_1: {
expect: { expect: {
(function() { (function() {
(function() { (function() {
f(1).bar = 1; var c;
c = f(1);
c.bar = 1;
})(); })();
})(); })();
} }
@@ -29,7 +30,6 @@ chained_evaluation_2: {
options = { options = {
collapse_vars: true, collapse_vars: true,
evaluate: true, evaluate: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -46,36 +46,10 @@ chained_evaluation_2: {
expect: { expect: {
(function() { (function() {
(function() { (function() {
var b = "long piece of string"; var c, b = "long piece of string";
f(b).bar = b;
})();
})();
}
}
chained_evaluation_3: {
options = {
collapse_vars: true,
evaluate: 10,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function() {
var a = "long piece of string";
(function() {
var b = a, c;
c = f(b); c = f(b);
c.bar = b; c.bar = b;
})(); })();
})(); })();
} }
expect: {
(function() {
(function() {
f("long piece of string").bar = "long piece of string";
})();
})();
}
} }

View File

@@ -1,7 +1,8 @@
issue_1639_1: { issue_1639_1: {
options = { options = {
booleans: true, booleans: true,
collapse_vars: true, cascade: true,
conditionals: true, conditionals: true,
evaluate: true, evaluate: true,
join_vars: true, join_vars: true,
@@ -11,6 +12,7 @@ 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) {
@@ -19,21 +21,21 @@ issue_1639_1: {
} }
} }
} }
console.log(a, b); console.log(a, b);
} }
expect: { expect: {
for (var a = 100, b = 10, L1 = 5, ignore; --L1 > 0;) { for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
--b; if (--b, !1) var ignore = 0;
}
console.log(a, b); console.log(a, b);
} }
expect_stdout: "100 6" expect_stdout: true
} }
issue_1639_2: { issue_1639_2: {
options = { options = {
booleans: true, booleans: true,
collapse_vars: true, cascade: true,
conditionals: true, conditionals: true,
evaluate: true, evaluate: true,
join_vars: true, join_vars: true,
@@ -42,12 +44,14 @@ 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: {
@@ -58,13 +62,13 @@ issue_1639_2: {
f19(), f19(),
console.log(a, b); console.log(a, b);
} }
expect_stdout: "101 10" expect_stdout: true
} }
issue_1639_3: { issue_1639_3: {
options = { options = {
booleans: true, booleans: true,
collapse_vars: true, cascade: true,
conditionals: true, conditionals: true,
evaluate: true, evaluate: true,
sequences: true, sequences: true,
@@ -80,5 +84,5 @@ issue_1639_3: {
a++, a++,
console.log(a, b); console.log(a, b);
} }
expect_stdout: "101 10" expect_stdout: true
} }

View File

@@ -1,6 +1,7 @@
f7: { f7: {
options = { options = {
booleans: true, booleans: true,
cascade: true,
collapse_vars: true, collapse_vars: true,
comparisons: true, comparisons: true,
conditionals: true, conditionals: true,
@@ -14,7 +15,6 @@ f7: {
negate_iife: true, negate_iife: true,
passes: 3, passes: 3,
properties: true, properties: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
sequences: true, sequences: true,
side_effects: true, side_effects: true,
@@ -35,7 +35,11 @@ f7: {
console.log(a, b); console.log(a, b);
} }
expect_exact: [ expect_exact: [
"console.log(100, 100);", "var b = 10;",
"",
"!function() {",
" for (;b = 100, !1; ) ;",
"}(), console.log(100, b);",
] ]
expect_stdout: "100 100" expect_stdout: true
} }

View File

@@ -1,6 +1,5 @@
side_effects_catch: { side_effects_catch: {
options = { options = {
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
unused: true, unused: true,
@@ -35,7 +34,6 @@ side_effects_catch: {
side_effects_else: { side_effects_else: {
options = { options = {
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
unused: true, unused: true,
@@ -64,7 +62,6 @@ side_effects_else: {
side_effects_finally: { side_effects_finally: {
options = { options = {
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
unused: true, unused: true,
@@ -101,7 +98,6 @@ side_effects_finally: {
side_effects_label: { side_effects_label: {
options = { options = {
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
unused: true, unused: true,
@@ -134,7 +130,6 @@ side_effects_label: {
side_effects_switch: { side_effects_switch: {
options = { options = {
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
side_effects: true, side_effects: true,
unused: true, unused: true,

View File

@@ -1,10 +1,10 @@
mangle_catch: { mangle_catch: {
options = { options = {
ie8: false, screw_ie8: true,
toplevel: false, toplevel: false,
} }
mangle = { mangle = {
ie8: false, screw_ie8: true,
toplevel: false, toplevel: false,
} }
input: { input: {
@@ -22,11 +22,11 @@ mangle_catch: {
mangle_catch_ie8: { mangle_catch_ie8: {
options = { options = {
ie8: true, screw_ie8: false,
toplevel: false, toplevel: false,
} }
mangle = { mangle = {
ie8: true, screw_ie8: false,
toplevel: false, toplevel: false,
} }
input: { input: {
@@ -44,11 +44,11 @@ mangle_catch_ie8: {
mangle_catch_var: { mangle_catch_var: {
options = { options = {
ie8: false, screw_ie8: true,
toplevel: false, toplevel: false,
} }
mangle = { mangle = {
ie8: false, screw_ie8: true,
toplevel: false, toplevel: false,
} }
input: { input: {
@@ -66,11 +66,11 @@ mangle_catch_var: {
mangle_catch_var_ie8: { mangle_catch_var_ie8: {
options = { options = {
ie8: true, screw_ie8: false,
toplevel: false, toplevel: false,
} }
mangle = { mangle = {
ie8: true, screw_ie8: false,
toplevel: false, toplevel: false,
} }
input: { input: {
@@ -88,11 +88,11 @@ mangle_catch_var_ie8: {
mangle_catch_toplevel: { mangle_catch_toplevel: {
options = { options = {
ie8: false, screw_ie8: true,
toplevel: true, toplevel: true,
} }
mangle = { mangle = {
ie8: false, screw_ie8: true,
toplevel: true, toplevel: true,
} }
input: { input: {
@@ -104,17 +104,17 @@ mangle_catch_toplevel: {
} }
console.log(a); console.log(a);
} }
expect_exact: 'var c="FAIL";try{throw 1}catch(o){c="PASS"}console.log(c);' expect_exact: 'var o="FAIL";try{throw 1}catch(c){o="PASS"}console.log(o);'
expect_stdout: "PASS" expect_stdout: "PASS"
} }
mangle_catch_ie8_toplevel: { mangle_catch_ie8_toplevel: {
options = { options = {
ie8: true, screw_ie8: false,
toplevel: true, toplevel: true,
} }
mangle = { mangle = {
ie8: true, screw_ie8: false,
toplevel: true, toplevel: true,
} }
input: { input: {
@@ -132,11 +132,11 @@ mangle_catch_ie8_toplevel: {
mangle_catch_var_toplevel: { mangle_catch_var_toplevel: {
options = { options = {
ie8: false, screw_ie8: true,
toplevel: true, toplevel: true,
} }
mangle = { mangle = {
ie8: false, screw_ie8: true,
toplevel: true, toplevel: true,
} }
input: { input: {
@@ -148,17 +148,17 @@ mangle_catch_var_toplevel: {
} }
console.log(a); console.log(a);
} }
expect_exact: 'var r="FAIL";try{throw 1}catch(o){var r="PASS"}console.log(r);' expect_exact: 'var o="FAIL";try{throw 1}catch(r){var o="PASS"}console.log(o);'
expect_stdout: "PASS" expect_stdout: "PASS"
} }
mangle_catch_var_ie8_toplevel: { mangle_catch_var_ie8_toplevel: {
options = { options = {
ie8: true, screw_ie8: false,
toplevel: true, toplevel: true,
} }
mangle = { mangle = {
ie8: true, screw_ie8: false,
toplevel: true, toplevel: true,
} }
input: { input: {
@@ -176,11 +176,11 @@ mangle_catch_var_ie8_toplevel: {
mangle_catch_redef_1: { mangle_catch_redef_1: {
options = { options = {
ie8: false, screw_ie8: true,
toplevel: false, toplevel: false,
} }
mangle = { mangle = {
ie8: false, screw_ie8: true,
toplevel: false, toplevel: false,
} }
input: { input: {
@@ -198,11 +198,11 @@ mangle_catch_redef_1: {
mangle_catch_redef_1_ie8: { mangle_catch_redef_1_ie8: {
options = { options = {
ie8: true, screw_ie8: false,
toplevel: false, toplevel: false,
} }
mangle = { mangle = {
ie8: true, screw_ie8: false,
toplevel: false, toplevel: false,
} }
input: { input: {
@@ -220,11 +220,11 @@ mangle_catch_redef_1_ie8: {
mangle_catch_redef_1_toplevel: { mangle_catch_redef_1_toplevel: {
options = { options = {
ie8: false, screw_ie8: true,
toplevel: true, toplevel: true,
} }
mangle = { mangle = {
ie8: false, screw_ie8: true,
toplevel: true, toplevel: true,
} }
input: { input: {
@@ -242,11 +242,11 @@ mangle_catch_redef_1_toplevel: {
mangle_catch_redef_1_ie8_toplevel: { mangle_catch_redef_1_ie8_toplevel: {
options = { options = {
ie8: true, screw_ie8: false,
toplevel: true, toplevel: true,
} }
mangle = { mangle = {
ie8: true, screw_ie8: false,
toplevel: true, toplevel: true,
} }
input: { input: {
@@ -264,11 +264,11 @@ mangle_catch_redef_1_ie8_toplevel: {
mangle_catch_redef_2: { mangle_catch_redef_2: {
options = { options = {
ie8: false, screw_ie8: true,
toplevel: false, toplevel: false,
} }
mangle = { mangle = {
ie8: false, screw_ie8: true,
toplevel: false, toplevel: false,
} }
input: { input: {
@@ -285,11 +285,11 @@ mangle_catch_redef_2: {
mangle_catch_redef_2_ie8: { mangle_catch_redef_2_ie8: {
options = { options = {
ie8: true, screw_ie8: false,
toplevel: false, toplevel: false,
} }
mangle = { mangle = {
ie8: true, screw_ie8: false,
toplevel: false, toplevel: false,
} }
input: { input: {
@@ -306,11 +306,11 @@ mangle_catch_redef_2_ie8: {
mangle_catch_redef_2_toplevel: { mangle_catch_redef_2_toplevel: {
options = { options = {
ie8: false, screw_ie8: true,
toplevel: true, toplevel: true,
} }
mangle = { mangle = {
ie8: false, screw_ie8: true,
toplevel: true, toplevel: true,
} }
input: { input: {
@@ -327,11 +327,11 @@ mangle_catch_redef_2_toplevel: {
mangle_catch_redef_2_ie8_toplevel: { mangle_catch_redef_2_ie8_toplevel: {
options = { options = {
ie8: true, screw_ie8: false,
toplevel: true, toplevel: true,
} }
mangle = { mangle = {
ie8: true, screw_ie8: false,
toplevel: true, toplevel: true,
} }
input: { input: {
@@ -345,95 +345,3 @@ mangle_catch_redef_2_ie8_toplevel: {
expect_exact: 'try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);' expect_exact: 'try{throw"FAIL1"}catch(o){var o="FAIL2"}console.log(o);'
expect_stdout: "undefined" expect_stdout: "undefined"
} }
mangle_catch_redef_3: {
mangle = {
ie8: false,
toplevel: false,
}
input: {
var o = "PASS";
try {
throw 0;
} catch (o) {
(function() {
function f() {
o = "FAIL";
}
f(), f();
})();
}
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: true
}
mangle_catch_redef_3_toplevel: {
mangle = {
ie8: false,
toplevel: true,
}
input: {
var o = "PASS";
try {
throw 0;
} catch (o) {
(function() {
function f() {
o = "FAIL";
}
f(), f();
})();
}
console.log(o);
}
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
expect_stdout: true
}
mangle_catch_redef_3_ie8: {
mangle = {
ie8: true,
toplevel: false,
}
input: {
var o = "PASS";
try {
throw 0;
} catch (o) {
(function() {
function f() {
o = "FAIL";
}
f(), f();
})();
}
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: true
}
mangle_catch_redef_3_ie8_toplevel: {
mangle = {
ie8: true,
toplevel: true,
}
input: {
var o = "PASS";
try {
throw 0;
} catch (o) {
(function() {
function f() {
o = "FAIL";
}
f(), f();
})();
}
console.log(o);
}
expect_exact: 'var c="PASS";try{throw 0}catch(c){(function(){function o(){c="FAIL"}o(),o()})()}console.log(c);'
expect_stdout: true
}

View File

@@ -1,6 +1,27 @@
function_iife_catch: { function_iife_catch: {
mangle = { mangle = {
ie8: false, screw_ie8: true,
}
input: {
function f(n) {
!function() {
try {
throw 0;
} catch (n) {
var a = 1;
console.log(n, a);
}
}();
}
f();
}
expect_exact: "function f(o){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();"
expect_stdout: "0 1"
}
function_iife_catch_ie8: {
mangle = {
screw_ie8: false,
} }
input: { input: {
function f(n) { function f(n) {
@@ -19,58 +40,37 @@ function_iife_catch: {
expect_stdout: "0 1" expect_stdout: "0 1"
} }
function_iife_catch_ie8: {
mangle = {
ie8: true,
}
input: {
function f(n) {
!function() {
try {
throw 0;
} catch (n) {
var a = 1;
console.log(n, a);
}
}();
}
f();
}
expect_exact: "function f(c){!function(){try{throw 0}catch(c){var o=1;console.log(c,o)}}()}f();"
expect_stdout: "0 1"
}
function_catch_catch: { function_catch_catch: {
mangle = { mangle = {
ie8: false, screw_ie8: true,
} }
input: { input: {
var o = 0; var o = 0;
function f() { function f() {
try { try {
throw 1; throw 1;
} catch (c) { } catch (c) {
try { try {
throw 2; throw 2;
} catch (o) { } catch (o) {
var o = 3; var o = 3;
console.log(o); console.log(o);
} }
} }
console.log(o); console.log(o);
} }
f(); f();
} }
expect_exact: "var o=0;function f(){try{throw 1}catch(o){try{throw 2}catch(c){var c=3;console.log(c)}}console.log(c)}f();" expect_exact: "var o=0;function f(){try{throw 1}catch(c){try{throw 2}catch(o){var o=3;console.log(o)}}console.log(o)}f();"
expect_stdout: [ expect_stdout: [
"3", "3",
"undefined", "undefined",
] ]
} }
function_catch_catch_ie8: { function_catch_catch_ie8: {
mangle = { mangle = {
ie8: true, screw_ie8: false,
} }
input: { input: {
var o = 0; var o = 0;

View File

@@ -7,7 +7,7 @@ case_1: {
input: { input: {
var a = 0, b = 1; var a = 0, b = 1;
switch (true) { switch (true) {
case a || true: case a, true:
default: default:
b = 2; b = 2;
case true: case true:
@@ -17,7 +17,7 @@ case_1: {
expect: { expect: {
var a = 0, b = 1; var a = 0, b = 1;
switch (true) { switch (true) {
case a || true: case a, true:
b = 2; b = 2;
} }
console.log(a, b); console.log(a, b);

View File

@@ -1,7 +1,5 @@
mangle_props: { mangle_props: {
mangle = { mangle_props = {}
properties: true,
}
input: { input: {
var obj = { var obj = {
undefined: 1, undefined: 1,
@@ -46,7 +44,7 @@ mangle_props: {
obj[1/0], obj[1/0],
obj["Infinity"], obj["Infinity"],
obj[-1/0], obj[-1/0],
obj[-(1/0)], obj[-1/0],
obj["-Infinity"], obj["-Infinity"],
obj[null], obj[null],
obj["null"] obj["null"]
@@ -56,12 +54,10 @@ mangle_props: {
} }
numeric_literal: { numeric_literal: {
mangle = {
properties: true,
}
beautify = { beautify = {
beautify: true, beautify: true,
} }
mangle_props = {}
input: { input: {
var obj = { var obj = {
0: 0, 0: 0,
@@ -84,19 +80,19 @@ numeric_literal: {
' 0: 0,', ' 0: 0,',
' "-0": 1,', ' "-0": 1,',
' 42: 2,', ' 42: 2,',
' 42: 3,', ' "42": 3,',
' 37: 4,', ' 37: 4,',
' o: 5,', ' a: 5,',
' 1e42: 6,', ' 1e42: 6,',
' b: 7,', ' b: 7,',
' 1e42: 8', ' "1e+42": 8',
'};', '};',
'', '',
'console.log(obj[-0], obj[-""], obj["-0"]);', 'console.log(obj[-0], obj[-""], obj["-0"]);',
'', '',
'console.log(obj[42], obj["42"]);', 'console.log(obj[42], obj["42"]);',
'', '',
'console.log(obj[37], obj["o"], obj[37], obj["37"]);', 'console.log(obj[37], obj["a"], obj[37], obj["37"]);',
'', '',
'console.log(obj[1e42], obj["b"], obj["1e+42"]);', 'console.log(obj[1e42], obj["b"], obj["1e+42"]);',
] ]
@@ -109,9 +105,7 @@ numeric_literal: {
} }
identifier: { identifier: {
mangle = { mangle_props = {}
properties: true,
}
input: { input: {
var obj = { var obj = {
abstract: 1, abstract: 1,
@@ -179,32 +173,32 @@ identifier: {
} }
expect: { expect: {
var obj = { var obj = {
e: 1, a: 1,
t: 2, b: 2,
n: 3, c: 3,
a: 4, d: 4,
i: 5, e: 5,
o: 6, f: 6,
r: 7, g: 7,
l: 8, h: 8,
s: 9, i: 9,
c: 10, j: 10,
f: 11, k: 11,
u: 12, l: 12,
d: 13, m: 13,
h: 14, n: 14,
p: 15, o: 15,
b: 16, p: 16,
v: 17, q: 17,
w: 18, r: 18,
y: 19, s: 19,
g: 20, t: 20,
m: 21, u: 21,
k: 22, v: 22,
x: 23, w: 23,
j: 24, x: 24,
z: 25, y: 25,
q: 26, z: 26,
A: 27, A: 27,
B: 28, B: 28,
C: 29, C: 29,
@@ -235,11 +229,11 @@ identifier: {
Z: 54, Z: 54,
$: 55, $: 55,
_: 56, _: 56,
ee: 57, aa: 57,
te: 58, ba: 58,
ne: 59, ca: 59,
ae: 60, da: 60,
ie: 61, ea: 61,
}; };
} }
} }

View File

@@ -1,8 +1,6 @@
unary_prefix: { unary_prefix: {
options = { options = {
evaluate: true, evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
unused: true, unused: true,
} }
@@ -12,6 +10,10 @@ unary_prefix: {
return x; return x;
}()); }());
} }
expect_exact: "console.log(-2/3);" expect: {
console.log(function() {
return -2 / 3;
}());
}
expect_stdout: true expect_stdout: true
} }

View File

@@ -1,7 +1,6 @@
iife_for: { iife_for: {
options = { options = {
negate_iife: true, negate_iife: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
unused: true, unused: true,
@@ -27,7 +26,6 @@ iife_for: {
iife_for_in: { iife_for_in: {
options = { options = {
negate_iife: true, negate_iife: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
unused: true, unused: true,
@@ -53,7 +51,6 @@ iife_for_in: {
iife_do: { iife_do: {
options = { options = {
negate_iife: true, negate_iife: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
unused: true, unused: true,
@@ -83,7 +80,6 @@ iife_do: {
iife_while: { iife_while: {
options = { options = {
negate_iife: true, negate_iife: true,
reduce_funcs: true,
reduce_vars: true, reduce_vars: true,
toplevel: true, toplevel: true,
unused: true, unused: true,
@@ -125,8 +121,8 @@ label_do: {
label_while: { label_while: {
options = { options = {
dead_code: true,
evaluate: true, evaluate: true,
dead_code: true,
loops: true, loops: true,
} }
input: { input: {
@@ -134,5 +130,5 @@ label_while: {
L: while (0) continue L; L: while (0) continue L;
} }
} }
expect_exact: "function f(){L:0}" expect_exact: "function f(){L:;}"
} }

View File

@@ -1,8 +1,6 @@
do_not_update_lhs: { do_not_update_lhs: {
options = { options = {
global_defs: { global_defs: { DEBUG: 0 }
DEBUG: 0,
},
} }
input: { input: {
DEBUG++; DEBUG++;
@@ -18,9 +16,7 @@ do_not_update_lhs: {
do_update_rhs: { do_update_rhs: {
options = { options = {
global_defs: { global_defs: { DEBUG: 0 }
DEBUG: 0,
},
} }
input: { input: {
MY_DEBUG = DEBUG; MY_DEBUG = DEBUG;
@@ -39,10 +35,10 @@ mixed: {
DEBUG: 0, DEBUG: 0,
ENV: 1, ENV: 1,
FOO: 2, FOO: 2,
}, }
} }
input: { input: {
var ENV = 3; const ENV = 3;
var FOO = 4; var FOO = 4;
f(ENV * 10); f(ENV * 10);
--FOO; --FOO;
@@ -53,7 +49,7 @@ mixed: {
x = DEBUG; x = DEBUG;
} }
expect: { expect: {
var ENV = 3; const ENV = 3;
var FOO = 4; var FOO = 4;
f(10); f(10);
--FOO; --FOO;
@@ -64,11 +60,11 @@ mixed: {
x = 0; x = 0;
} }
expect_warnings: [ expect_warnings: [
"WARN: global_defs ENV redefined [test/compress/issue-208.js:1,12]", 'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,14]',
"WARN: global_defs FOO redefined [test/compress/issue-208.js:2,12]", 'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]',
"WARN: global_defs FOO redefined [test/compress/issue-208.js:4,10]", 'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]',
"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:5,8]", 'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]',
"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:6,8]", 'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:46,8]',
"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:7,8]", 'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:47,8]',
] ]
} }

View File

@@ -1,7 +1,5 @@
return_with_no_value_in_if_body: { return_with_no_value_in_if_body: {
options = { options = { conditionals: true };
conditionals: true,
}
input: { input: {
function foo(bar) { function foo(bar) {
if (bar) { if (bar) {

View File

@@ -1,33 +0,0 @@
insert_semicolon: {
beautify = {
beautify: true,
comments: "all",
}
input: {
var a
/* foo */ var b
}
expect_exact: [
"var a",
"/* foo */;",
"",
"var b;",
]
}
unary_postfix: {
beautify = {
beautify: true,
comments: "all",
}
input: {
a
/* foo */++b
}
expect_exact: [
"a",
"/* foo */;",
"",
"++b;",
]
}

View File

@@ -1,7 +1,5 @@
issue_267: { issue_267: {
options = { options = { comparisons: true };
comparisons: true,
}
input: { input: {
x = a % b / b * c * 2; x = a % b / b * c * 2;
x = a % b * 2 x = a % b * 2

View File

@@ -1,111 +1,66 @@
issue_269_1: { issue_269_1: {
options = { options = {unsafe: true};
unsafe: true, input: {
} f(
input: { String(x),
var x = {}; Number(x),
console.log( Boolean(x),
String(x),
Number(x),
Boolean(x),
String(), String(),
Number(), Number(),
Boolean() Boolean()
); );
} }
expect: { expect: {
var x = {}; f(
console.log( x + '', +x, !!x,
x + "", +x, !!x, '', 0, false
"", 0, false );
); }
}
expect_stdout: true
} }
issue_269_dangers: { issue_269_dangers: {
options = { options = {unsafe: true};
unsafe: true, input: {
} f(
input: { String(x, x),
var x = {}; Number(x, x),
console.log( Boolean(x, x)
String(x, x), );
Number(x, x), }
Boolean(x, x) expect: {
); f(String(x, x), Number(x, x), Boolean(x, x));
} }
expect: {
var x = {};
console.log(String(x, x), Number(x, x), Boolean(x, x));
}
expect_stdout: true
} }
issue_269_in_scope: { issue_269_in_scope: {
options = { options = {unsafe: true};
unsafe: true, input: {
} var String, Number, Boolean;
input: { f(
var String, Number, Boolean; String(x),
var x = {}; Number(x, x),
console.log( Boolean(x)
String(x), );
Number(x, x), }
Boolean(x) expect: {
); var String, Number, Boolean;
} f(String(x), Number(x, x), Boolean(x));
expect: { }
var String, Number, Boolean;
var x = {};
console.log(String(x), Number(x, x), Boolean(x));
}
expect_stdout: true
} }
strings_concat: { strings_concat: {
options = { options = {unsafe: true};
strings: true, input: {
unsafe: true, f(
} String(x + 'str'),
input: { String('str' + x)
var x = {}; );
console.log( }
String(x + "str"), expect: {
String("str" + x) f(
); x + 'str',
} 'str' + x
expect: { );
var x = {}; }
console.log(
x + "str",
"str" + x
);
}
expect_stdout: true
}
regexp: {
options = {
evaluate: true,
unsafe: true,
}
input: {
RegExp("foo");
RegExp("bar", "ig");
RegExp(foo);
RegExp("bar", ig);
RegExp("should", "fail");
}
expect: {
/foo/;
/bar/ig;
RegExp(foo);
RegExp("bar", ig);
RegExp("should", "fail");
}
expect_warnings: [
'WARN: Error converting RegExp("should","fail") [test/compress/issue-269.js:5,8]',
]
} }

View File

@@ -1,32 +0,0 @@
warn: {
options = {
evaluate: true,
inline: true,
passes: 2,
properties: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f() {
return g();
}
function g() {
return g["call" + "er"].arguments;
}
// 3
console.log(f(1, 2, 3).length);
}
expect: {
// TypeError: Cannot read property 'arguments' of null
console.log(function g() {
return g.caller.arguments;
}().length);
}
expect_warnings: [
"WARN: Function.prototype.arguments not supported [test/compress/issue-2719.js:5,19]",
"WARN: Function.prototype.caller not supported [test/compress/issue-2719.js:5,19]",
]
}

View File

@@ -1,498 +0,0 @@
collapse_vars_constants: {
options = {
collapse_vars: true,
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
function f1(x) {
var a = 4, b = x.prop, c = 5, d = sideeffect1(), e = sideeffect2();
return b + (function() { return d - a * e - c; })();
}
function f2(x) {
var a = 4, b = x.prop, c = 5, not_used = sideeffect1(), e = sideeffect2();
return b + (function() { return -a * e - c; })();
}
}
expect: {
function f1(x) {
var b = x.prop, d = sideeffect1(), e = sideeffect2();
return b + (d - 4 * e - 5);
}
function f2(x) {
var b = x.prop;
sideeffect1();
return b + (-4 * sideeffect2() - 5);
}
}
}
modified: {
options = {
collapse_vars: true,
inline: true,
unused: true,
}
input: {
function f5(b) {
var a = function() {
return b;
}();
return b++ + a;
}
console.log(f5(1));
}
expect: {
function f5(b) {
var a = b;
return b++ + a;
}
console.log(f5(1));
}
expect_stdout: "2"
}
ref_scope: {
options = {
collapse_vars: true,
inline: true,
unused: true,
}
input: {
console.log(function() {
var a = 1, b = 2, c = 3;
var a = c++, b = b /= a;
return function() {
return a;
}() + b;
}());
}
expect: {
console.log(function() {
var a = 1, b = 2, c = 3;
b = b /= a = c++;
return a + b;
}());
}
expect_stdout: true
}
safe_undefined: {
options = {
conditionals: true,
if_return: true,
inline: true,
unsafe: false,
unused: true,
}
mangle = {}
input: {
var a, c;
console.log(function(undefined) {
return function() {
if (a)
return b;
if (c)
return d;
};
}(1)());
}
expect: {
var a, c;
console.log(a ? b : c ? d : void 0);
}
expect_stdout: true
}
negate_iife_3: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: true,
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
}
expect: {
t ? console.log(true) : console.log(false);
}
}
negate_iife_3_off: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: false,
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
}
expect: {
t ? console.log(true) : console.log(false);
}
}
negate_iife_4: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: true,
sequences: true,
}
input: {
(function(){ return t })() ? console.log(true) : console.log(false);
(function(){
console.log("something");
})();
}
expect: {
t ? console.log(true) : console.log(false), void console.log("something");
}
}
negate_iife_5: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: true,
sequences: true,
}
input: {
if ((function(){ return t })()) {
foo(true);
} else {
bar(false);
}
(function(){
console.log("something");
})();
}
expect: {
t ? foo(true) : bar(false), void console.log("something");
}
}
negate_iife_5_off: {
options = {
conditionals: true,
expression: true,
inline: true,
negate_iife: false,
sequences: true,
}
input: {
if ((function(){ return t })()) {
foo(true);
} else {
bar(false);
}
(function(){
console.log("something");
})();
}
expect: {
t ? foo(true) : bar(false), void console.log("something");
}
}
issue_1254_negate_iife_true: {
options = {
expression: true,
inline: true,
negate_iife: true,
}
input: {
(function() {
return function() {
console.log('test')
};
})()();
}
expect_exact: 'void console.log("test");'
expect_stdout: true
}
issue_1254_negate_iife_nested: {
options = {
expression: true,
inline: true,
negate_iife: true,
}
input: {
(function() {
return function() {
console.log('test')
};
})()()()()();
}
expect_exact: '(void console.log("test"))()()();'
}
negate_iife_issue_1073: {
options = {
conditionals: true,
evaluate: true,
inline: true,
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
unused: true,
}
input: {
new (function(a) {
return function Foo() {
this.x = a;
console.log(this);
};
}(7))();
}
expect: {
new function() {
this.x = 7,
console.log(this);
}();
}
expect_stdout: true
}
issue_1288_side_effects: {
options = {
conditionals: true,
evaluate: true,
inline: true,
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
if (w) ;
else {
(function f() {})();
}
if (!x) {
(function() {
x = {};
})();
}
if (y)
(function() {})();
else
(function(z) {
return z;
})(0);
}
expect: {
w;
x || (x = {});
y;
}
}
inner_var_for_in_1: {
options = {
evaluate: true,
inline: true,
reduce_funcs: true,
reduce_vars: true,
}
input: {
function f() {
var a = 1, b = 2;
for (b in (function() {
return x(a, b, c);
})()) {
var c = 3, d = 4;
x(a, b, c, d);
}
x(a, b, c, d);
}
}
expect: {
function f() {
var a = 1, b = 2;
for (b in x(1, b, c)) {
var c = 3, d = 4;
x(1, b, c, d);
}
x(1, b, c, d);
}
}
}
issue_1595_3: {
options = {
evaluate: true,
inline: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
input: {
(function f(a) {
return g(a + 1);
})(2);
}
expect: {
g(3);
}
}
issue_1758: {
options = {
inline: true,
sequences: true,
side_effects: true,
}
input: {
console.log(function(c) {
var undefined = 42;
return function() {
c--;
c--, c.toString();
return;
}();
}());
}
expect: {
console.log(function(c) {
var undefined = 42;
return c--, c--, void c.toString();
}());
}
expect_stdout: "undefined"
}
wrap_iife: {
options = {
inline: true,
negate_iife: false,
}
beautify = {
wrap_iife: true,
}
input: {
(function() {
return function() {
console.log('test')
};
})()();
}
expect_exact: 'void console.log("test");'
}
wrap_iife_in_expression: {
options = {
inline: true,
negate_iife: false,
}
beautify = {
wrap_iife: true,
}
input: {
foo = (function() {
return bar();
})();
}
expect_exact: 'foo=bar();'
}
wrap_iife_in_return_call: {
options = {
inline: true,
negate_iife: false,
}
beautify = {
wrap_iife: true,
}
input: {
(function() {
return (function() {
console.log('test')
})();
})()();
}
expect_exact: '(void console.log("test"))();'
}
pure_annotation_1: {
options = {
inline: true,
side_effects: true,
}
input: {
/*@__PURE__*/(function() {
console.log("hello");
}());
}
expect_exact: ""
}
pure_annotation_2: {
options = {
collapse_vars: true,
inline: true,
side_effects: true,
}
input: {
/*@__PURE__*/(function(n) {
console.log("hello", n);
}(42));
}
expect_exact: ""
}
drop_fargs: {
options = {
collapse_vars: true,
inline: true,
keep_fargs: false,
side_effects: true,
unused: true,
}
input: {
var a = 1;
!function(a_1) {
a++;
}(a++ + (a && a.var));
console.log(a);
}
expect: {
var a = 1;
++a && a.var, a++;
console.log(a);
}
expect_stdout: "3"
}
keep_fargs: {
options = {
collapse_vars: true,
inline: true,
keep_fargs: true,
side_effects: true,
unused: true,
}
input: {
var a = 1;
!function(a_1) {
a++;
}(a++ + (a && a.var));
console.log(a);
}
expect: {
var a = 1;
++a && a.var, a++;
console.log(a);
}
expect_stdout: "3"
}

View File

@@ -1,37 +0,0 @@
comparison_with_undefined: {
options = {
comparisons: true,
}
input: {
a == undefined;
a != undefined;
a === undefined;
a !== undefined;
undefined == a;
undefined != a;
undefined === a;
undefined !== a;
void 0 == a;
void 0 != a;
void 0 === a;
void 0 !== a;
}
expect: {
null == a;
null != a;
void 0 === a;
void 0 !== a;
null == a;
null != a;
void 0 === a;
void 0 !== a;
null == a;
null != a;
void 0 === a;
void 0 !== a;
}
}

View File

@@ -1,21 +0,0 @@
inline_script_off: {
beautify = {
inline_script: false,
}
input: {
console.log("</sCrIpT>");
}
expect_exact: 'console.log("</sCrIpT>");'
expect_stdout: "</sCrIpT>"
}
inline_script_on: {
beautify = {
inline_script: true,
}
input: {
console.log("</sCrIpT>");
}
expect_exact: 'console.log("<\\/sCrIpT>");'
expect_stdout: "</sCrIpT>"
}

View File

@@ -1,6 +1,6 @@
collapse: { collapse: {
options = { options = {
collapse_vars: true, cascade: true,
sequences: true, sequences: true,
side_effects: true, side_effects: true,
unused: true, unused: true,
@@ -41,7 +41,7 @@ collapse: {
return void 0 !== ('function' === typeof b ? b() : b) && c(); return void 0 !== ('function' === typeof b ? b() : b) && c();
} }
function f2(b) { function f2(b) {
return 'stirng' == typeof ('function' === typeof (b = c()) ? b() : b) && d(); return b = c(), 'stirng' == typeof ('function' === typeof b ? b() : b) && d();
} }
function f3(c) { function f3(c) {
var a; var a;

View File

@@ -1,128 +0,0 @@
mangle: {
mangle = {
toplevel: true,
}
input: {
var e = eval, x = 42;
(function() {
console.log(e("typeof x"));
})();
}
expect: {
var e = eval, x = 42;
(function() {
console.log(e("typeof x"));
})();
}
expect_stdout: true
}
compress: {
options = {
collapse_vars: true,
inline: true,
unused: true,
}
input: {
console.log(function() {
var a = 42;
return eval("typeof a");
}(), function(e) {
var a = null;
return e("typeof a");
}(eval), function(eval) {
var a = false;
return eval("typeof a");
}(eval), function(f) {
var a = "STRING";
var eval = f;
return eval("typeof a");
}(eval), function(g) {
var a = eval;
function eval() {
return g;
}
return eval()("typeof a");
}(eval));
}
expect: {
console.log(function() {
var a = 42;
return eval("typeof a");
}(), (0, eval)("typeof a"), function(eval) {
var a = false;
return eval("typeof a");
}(eval), function(f) {
var a = "STRING";
var eval = f;
return eval("typeof a");
}(eval), function(g) {
var a = eval;
function eval() {
return g;
}
return eval()("typeof a");
}(eval));
}
expect_stdout: "number undefined boolean string undefined"
}
call_arg_1: {
mangle = {
toplevel: true,
}
input: {
var z = "foo";
(function() {
var z = false;
(function(e) {
var z = 42;
e("console.log(typeof z)");
})(eval);
})();
}
expect: {
var z = "foo";
(function() {
var o = false;
(function(o) {
var a = 42;
o("console.log(typeof z)");
})(eval);
})();
}
expect_stdout: true
}
call_arg_2: {
mangle = {
toplevel: true,
}
input: {
function eval() {
console.log("PASS");
}
var z = "foo";
(function() {
var z = false;
(function(e) {
var z = 42;
e("console.log(typeof z)");
})(eval);
})();
}
expect: {
function n() {
console.log("PASS");
}
var o = "foo";
(function() {
var o = false;
(function(o) {
var n = 42;
o("console.log(typeof z)");
})(n);
})();
}
expect_stdout: "PASS"
}

View File

@@ -1,7 +1,5 @@
issue_44_valid_ast_1: { issue_44_valid_ast_1: {
options = { options = { unused: true };
unused: true,
}
input: { input: {
function a(b) { function a(b) {
for (var i = 0, e = b.qoo(); ; i++) {} for (var i = 0, e = b.qoo(); ; i++) {}
@@ -16,9 +14,7 @@ issue_44_valid_ast_1: {
} }
issue_44_valid_ast_2: { issue_44_valid_ast_2: {
options = { options = { unused: true };
unused: true,
}
input: { input: {
function a(b) { function a(b) {
if (foo) for (var i = 0, e = b.qoo(); ; i++) {} if (foo) for (var i = 0, e = b.qoo(); ; i++) {}

View File

@@ -1,8 +1,8 @@
keep_continue: { keep_continue: {
options = { options = {
dead_code: true, dead_code: true,
evaluate: true, evaluate: true
} };
input: { input: {
while (a) { while (a) {
if (b) { if (b) {

View File

@@ -1,5 +1,5 @@
NaN_and_Infinity_must_have_parens: { NaN_and_Infinity_must_have_parens: {
options = {} options = {};
input: { input: {
Infinity.toString(); Infinity.toString();
NaN.toString(); NaN.toString();
@@ -11,7 +11,7 @@ NaN_and_Infinity_must_have_parens: {
} }
NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: { NaN_and_Infinity_should_not_be_replaced_when_they_are_redefined: {
options = {} options = {};
input: { input: {
var Infinity, NaN; var Infinity, NaN;
Infinity.toString(); Infinity.toString();

View File

@@ -1,8 +1,8 @@
issue_611: { issue_611: {
options = { options = {
sequences: true, sequences: true,
side_effects: true, side_effects: true
} };
input: { input: {
define(function() { define(function() {
function fn() {} function fn() {}

View File

@@ -1,9 +1,9 @@
wrongly_optimized: { wrongly_optimized: {
options = { options = {
booleans: true,
conditionals: true, conditionals: true,
evaluate: true, booleans: true,
} evaluate: true
};
input: { input: {
function func() { function func() {
foo(); foo();
@@ -16,6 +16,7 @@ wrongly_optimized: {
function func() { function func() {
foo(); foo();
} }
func(), 1, bar(); // TODO: optimize to `func(), bar()`
(func(), 0) || bar();
} }
} }

View File

@@ -21,19 +21,19 @@ cond_5: {
} }
} }
expect: { expect: {
(some_condition() && some_other_condition() ? do_something : alternate)(); some_condition() && some_other_condition() ? do_something() : alternate();
if (some_condition() && some_other_condition()) do_something(); if (some_condition() && some_other_condition()) do_something();
} }
} }
dead_code_const_annotation_regex: { dead_code_const_annotation_regex: {
options = { options = {
booleans: true, booleans : true,
conditionals: true, conditionals : true,
dead_code: true, dead_code : true,
evaluate: true, evaluate : true,
expression: true, expression : true,
loops: true, loops : true,
} }
input: { input: {
var unused; var unused;
@@ -82,9 +82,8 @@ drop_value: {
wrongly_optimized: { wrongly_optimized: {
options = { options = {
booleans: true,
conditionals: true, conditionals: true,
dead_code: true, booleans: true,
evaluate: true, evaluate: true,
expression: true, expression: true,
} }
@@ -100,8 +99,8 @@ wrongly_optimized: {
function func() { function func() {
foo(); foo();
} }
func(), 1; // TODO: optimize to `func(), bar()`
bar(); if (func(), !0) bar();
} }
} }
@@ -160,7 +159,7 @@ negate_iife_4: {
})(); })();
} }
expect: { expect: {
!function(){ return t }() ? console.log(false) : console.log(true), function(){ (function(){ return t })() ? console.log(true) : console.log(false), function(){
console.log("something"); console.log("something");
}(); }();
} }
@@ -184,7 +183,7 @@ negate_iife_5: {
})(); })();
} }
expect: { expect: {
!function(){ return t }() ? bar(false) : foo(true), function(){ (function(){ return t })() ? foo(true) : bar(false), function(){
console.log("something"); console.log("something");
}(); }();
} }
@@ -196,7 +195,7 @@ negate_iife_5_off: {
expression: true, expression: true,
negate_iife: false, negate_iife: false,
sequences: true, sequences: true,
} };
input: { input: {
if ((function(){ return t })()) { if ((function(){ return t })()) {
foo(true); foo(true);
@@ -208,7 +207,7 @@ negate_iife_5_off: {
})(); })();
} }
expect: { expect: {
!function(){ return t }() ? bar(false) : foo(true), function(){ (function(){ return t })() ? foo(true) : bar(false), function(){
console.log("something"); console.log("something");
}(); }();
} }
@@ -249,9 +248,7 @@ issue_1254_negate_iife_nested: {
conditional: { conditional: {
options = { options = {
expression: true, expression: true,
pure_funcs: [ pure_funcs: [ "pure" ],
"pure"
],
side_effects: true, side_effects: true,
} }
input: { input: {

View File

@@ -1,45 +1,37 @@
dont_reuse_prop: { dont_reuse_prop: {
mangle = { mangle_props = {
properties: { regex: /asd/
regex: /asd/, };
},
}
input: { input: {
"aaaaaaaaaabbbbb";
var obj = {}; var obj = {};
obj.a = 123; obj.a = 123;
obj.asd = 256; obj.asd = 256;
console.log(obj.a); console.log(obj.a);
} }
expect: { expect: {
"aaaaaaaaaabbbbb";
var obj = {}; var obj = {};
obj.a = 123; obj.a = 123;
obj.b = 256; obj.b = 256;
console.log(obj.a); console.log(obj.a);
} }
expect_stdout: "123"
} }
unmangleable_props_should_always_be_reserved: { unmangleable_props_should_always_be_reserved: {
mangle = { mangle_props = {
properties: { regex: /asd/
regex: /asd/, };
},
}
input: { input: {
"aaaaaaaaaabbbbb";
var obj = {}; var obj = {};
obj.asd = 256; obj.asd = 256;
obj.a = 123; obj.a = 123;
console.log(obj.a); console.log(obj.a);
} }
expect: { expect: {
"aaaaaaaaaabbbbb";
var obj = {}; var obj = {};
obj.b = 256; obj.b = 256;
obj.a = 123; obj.a = 123;
console.log(obj.a); console.log(obj.a);
} }
expect_stdout: "123" }
}

View File

@@ -1,7 +1,7 @@
negate_booleans_1: { negate_booleans_1: {
options = { options = {
comparisons: true, comparisons: true
} };
input: { input: {
var a = !a || !b || !c || !d || !e || !f; var a = !a || !b || !c || !d || !e || !f;
} }
@@ -12,8 +12,8 @@ negate_booleans_1: {
negate_booleans_2: { negate_booleans_2: {
options = { options = {
comparisons: true, comparisons: true
} };
input: { input: {
var match = !x && // should not touch this one var match = !x && // should not touch this one
(!z || c) && (!z || c) &&

View File

@@ -1,31 +1,11 @@
remove_sequence: {
options = {
side_effects: true,
}
input: {
(0, 1, eval)();
(0, 1, logThis)();
(0, 1, _decorators.logThis)();
}
expect: {
(0, eval)();
logThis();
(0, _decorators.logThis)();
}
}
remove_redundant_sequence_items: { remove_redundant_sequence_items: {
options = { options = { side_effects: true };
side_effects: true,
}
input: { input: {
"use strict";
(0, 1, eval)(); (0, 1, eval)();
(0, 1, logThis)(); (0, 1, logThis)();
(0, 1, _decorators.logThis)(); (0, 1, _decorators.logThis)();
} }
expect: { expect: {
"use strict";
(0, eval)(); (0, eval)();
logThis(); logThis();
(0, _decorators.logThis)(); (0, _decorators.logThis)();
@@ -33,17 +13,13 @@ remove_redundant_sequence_items: {
} }
dont_remove_this_binding_sequence: { dont_remove_this_binding_sequence: {
options = { options = { side_effects: true };
side_effects: true,
}
input: { input: {
"use strict";
(0, eval)(); (0, eval)();
(0, logThis)(); (0, logThis)();
(0, _decorators.logThis)(); (0, _decorators.logThis)();
} }
expect: { expect: {
"use strict";
(0, eval)(); (0, eval)();
logThis(); logThis();
(0, _decorators.logThis)(); (0, _decorators.logThis)();

View File

@@ -2,25 +2,26 @@ dont_mangle_arguments: {
mangle = { mangle = {
}; };
options = { options = {
booleans: true, sequences : true,
comparisons: true, properties : true,
conditionals: true, dead_code : true,
dead_code: true, drop_debugger : true,
drop_debugger: true, conditionals : true,
evaluate: true, comparisons : true,
hoist_funs: true, evaluate : true,
hoist_vars: true, booleans : true,
if_return: true, loops : true,
join_vars: true, unused : true,
keep_fargs: true, hoist_funs : true,
keep_fnames: false, keep_fargs : true,
loops: true, keep_fnames : false,
negate_iife: false, hoist_vars : true,
properties: true, if_return : true,
sequences: true, join_vars : true,
side_effects: true, cascade : true,
unused: true, side_effects : true,
} negate_iife : false
};
input: { input: {
(function(){ (function(){
var arguments = arguments, not_arguments = 9; var arguments = arguments, not_arguments = 9;

View File

@@ -1,8 +1,8 @@
keep_var_for_in: { keep_var_for_in: {
options = { options = {
hoist_vars: true, hoist_vars: true,
unused: true, unused: true
} };
input: { input: {
(function(obj){ (function(obj){
var foo = 5; var foo = 5;

View File

@@ -1,11 +1,9 @@
this_binding_conditionals: { this_binding_conditionals: {
options = { options = {
conditionals: true, conditionals: true,
evaluate: true, evaluate : true
side_effects: true, };
}
input: { input: {
"use strict";
(1 && a)(); (1 && a)();
(0 || a)(); (0 || a)();
(0 || 1 && a)(); (0 || 1 && a)();
@@ -27,7 +25,6 @@ this_binding_conditionals: {
(1 ? eval : 0)(); (1 ? eval : 0)();
} }
expect: { expect: {
"use strict";
a(); a();
a(); a();
a(); a();
@@ -53,111 +50,48 @@ this_binding_conditionals: {
this_binding_collapse_vars: { this_binding_collapse_vars: {
options = { options = {
collapse_vars: true, collapse_vars: true,
unused: true, toplevel: true,
} };
input: { input: {
function f() { var c = a; c();
"use strict"; var d = a.b; d();
var c = a; c(); var e = eval; e();
var d = a.b; d();
var e = eval; e();
}
} }
expect: { expect: {
function f() { a();
"use strict"; (0, a.b)();
a(); (0, eval)();
(0, a.b)();
(0, eval)();
}
} }
} }
this_binding_side_effects: { this_binding_side_effects: {
options = { options = {
side_effects: true, side_effects : true
} };
input: { input: {
(function(foo) { (function (foo) {
(0, foo)(); (0, foo)();
(0, foo.bar)(); (0, foo.bar)();
(0, eval)("console.log(foo);"); (0, eval)('console.log(foo);');
}()); }());
(function(foo) { (function (foo) {
"use strict";
(0, foo)();
(0, foo.bar)();
(0, eval)("console.log(foo);");
}());
(function(foo) {
var eval = console; var eval = console;
(0, foo)(); (0, foo)();
(0, foo.bar)(); (0, foo.bar)();
(0, eval)("console.log(foo);"); (0, eval)('console.log(foo);');
}()); }());
} }
expect: { expect: {
(function(foo) { (function (foo) {
foo(); foo();
(0, foo.bar)(); (0, foo.bar)();
(0, eval)("console.log(foo);"); (0, eval)('console.log(foo);');
}()); }());
(function(foo) { (function (foo) {
"use strict";
foo();
(0, foo.bar)();
(0, eval)("console.log(foo);");
}());
(function(foo) {
var eval = console; var eval = console;
foo(); foo();
(0, foo.bar)(); (0, foo.bar)();
eval("console.log(foo);"); (0, eval)('console.log(foo);');
}()); }());
} }
} }
this_binding_sequences: {
options = {
sequences: true,
side_effects: true,
}
input: {
console.log(typeof function() {
return eval("this");
}());
console.log(typeof function() {
"use strict";
return eval("this");
}());
console.log(typeof function() {
return (0, eval)("this");
}());
console.log(typeof function() {
"use strict";
return (0, eval)("this");
}());
}
expect: {
console.log(typeof function() {
return eval("this");
}()),
console.log(typeof function() {
"use strict";
return eval("this");
}()),
console.log(typeof function() {
return (0, eval)("this");
}()),
console.log(typeof function() {
"use strict";
return (0, eval)("this");
}());
}
expect_stdout: [
"object",
"undefined",
"object",
"object",
]
}

View File

@@ -1,21 +1,9 @@
eval_collapse_vars: { eval_collapse_vars: {
options = { options = {
booleans: true, collapse_vars:true, sequences:false, properties:true, dead_code:true, conditionals:true,
collapse_vars: true, comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
comparisons: true, keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
conditionals: true, };
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: false,
side_effects: true,
unused: true,
}
input: { input: {
function f1() { function f1() {
var e = 7; var e = 7;
@@ -58,10 +46,7 @@ eval_collapse_vars: {
} }
eval_unused: { eval_unused: {
options = { options = { unused: true, keep_fargs: false };
keep_fargs: false,
unused: true,
}
input: { input: {
function f1(a, eval, c, d, e) { function f1(a, eval, c, d, e) {
return a('c') + eval; return a('c') + eval;

View File

@@ -1,19 +1,8 @@
issue979_reported: { issue979_reported: {
options = { options = {
booleans: true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons: true, comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
conditionals: true, keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
} }
input: { input: {
function f1() { function f1() {
@@ -41,20 +30,9 @@ issue979_reported: {
issue979_test_negated_is_best: { issue979_test_negated_is_best: {
options = { options = {
booleans: true, sequences:true, properties:true, dead_code:true, conditionals:true,
comparisons: true, comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
conditionals: true, keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
} }
input: { input: {
function f3() { function f3() {

Some files were not shown because too many files have changed in this diff Show More