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?**
<!-- Note: sub-optimal but correct code is not a bug -->
**Uglify version (`uglifyjs -V`)**
**JavaScript input**
- Bug report or feature request? <!-- Note: sub-optimal but correct code is not a bug -->
- `uglify-js` version (`uglifyjs -V`)
- JavaScript input - ideally as small as possible.
- The `uglifyjs` CLI command executed or `minify()` options used.
- An example of JavaScript output produced and/or the error or warning.
<!--
A complete parsable JS program exhibiting the issue with
UglifyJS alone - without third party tools or libraries.
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.
Note: the release version of uglify-js only supports ES5. Those wishing
to minify ES6 should use the experimental harmony branch.
-->

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:
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
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.
https://github.com/mishoo/UglifyJS
https://github.com/mishoo/UglifyJS2
-------------------------------- (C) ---------------------------------
@@ -43,9 +43,11 @@
"use strict";
(function() {
function normalize_directives(body) {
(function(){
var normalize_directives = function(body) {
var in_directive = true;
for (var i = 0; i < body.length; i++) {
if (in_directive && body[i] instanceof AST_Statement && body[i].body instanceof AST_String) {
body[i] = new AST_Directive({
@@ -57,8 +59,9 @@
in_directive = false;
}
}
return body;
}
};
var MOZ_TO_ME = {
Program: function(M) {
@@ -111,7 +114,7 @@
var args = {
start : my_start_token(key),
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)
};
if (M.kind == "init") return new AST_ObjectKeyVal(args);
@@ -126,7 +129,7 @@
return new AST_Array({
start : my_start_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);
})
});
@@ -135,18 +138,14 @@
return new AST_Object({
start : my_start_token(M),
end : my_end_token(M),
properties : M.properties.map(function(prop) {
properties : M.properties.map(function(prop){
prop.type = "Property";
return from_moz(prop)
})
});
},
SequenceExpression: function(M) {
return new AST_Sequence({
start : my_start_token(M),
end : my_end_token(M),
expressions: M.expressions.map(from_moz)
});
return AST_Seq.from_array(M.expressions.map(from_moz));
},
MemberExpression: function(M) {
return new (M.computed ? AST_Sub : AST_Dot)({
@@ -165,7 +164,7 @@
});
},
VariableDeclaration: function(M) {
return new AST_Var({
return new (M.kind === "const" ? AST_Const : AST_Var)({
start : my_start_token(M),
end : my_end_token(M),
definitions : M.declarations.map(from_moz)
@@ -177,17 +176,6 @@
end : my_end_token(M)
};
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) {
case "string":
args.value = val;
@@ -197,12 +185,22 @@
return new AST_Number(args);
case "boolean":
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) {
var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
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 == "FunctionDeclaration" ? (p.id === M ? AST_SymbolDefun : AST_SymbolFunarg)
: p.type == "CatchClause" ? AST_SymbolCatch
@@ -212,14 +210,7 @@
end : my_end_token(M),
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 =
@@ -252,6 +243,7 @@
map("VariableDeclarator", AST_VarDef, "id>name, init>value");
map("CatchClause", AST_Catch, "param>argname, body%body");
map("ThisExpression", AST_This);
map("BinaryExpression", 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");
@@ -328,15 +320,15 @@
def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
return {
type: "VariableDeclaration",
kind: "var",
kind: M instanceof AST_Const ? "const" : "var",
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 {
type: "SequenceExpression",
expressions: M.expressions.map(to_moz)
expressions: M.to_array().map(to_moz)
};
});
@@ -409,24 +401,19 @@
var def = M.definition();
return {
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) {
var flags = M.value.toString().match(/[gimuy]*$/)[0];
var value = "/" + M.value.raw_source + "/" + flags;
var value = M.value;
return {
type: "Literal",
value: value,
raw: value,
raw: value.toString(),
regex: {
pattern: M.value.raw_source,
flags: flags
pattern: value.source,
flags: value.toString().match(/[gimuy]*$/)[0]
}
};
});
@@ -487,7 +474,7 @@
endpos : range ? range[0] : moznode.start,
raw : raw_token(moznode),
});
}
};
function my_end_token(moznode) {
var loc = moznode.loc, end = loc && loc.end;
@@ -502,7 +489,7 @@
endpos : range ? range[1] : moznode.end,
raw : raw_token(moznode),
});
}
};
function map(moztype, mytype, propmap) {
var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
@@ -514,7 +501,7 @@
me_to_moz += "return {\n" +
"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);
if (!m) throw new Error("Can't understand property map: " + prop);
var moz = m[1], how = m[2], my = m[3];
@@ -557,7 +544,7 @@
);
MOZ_TO_ME[moztype] = moz_to_me;
def_to_moz(mytype, me_to_moz);
}
};
var FROM_MOZ_STACK = null;
@@ -566,28 +553,13 @@
var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
FROM_MOZ_STACK.pop();
return ret;
}
};
AST_Node.from_mozilla_ast = function(node) {
AST_Node.from_mozilla_ast = function(node){
var save_stack = FROM_MOZ_STACK;
FROM_MOZ_STACK = [];
var ast = from_moz(node);
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;
};
@@ -607,24 +579,24 @@
}
}
return moznode;
}
};
function def_to_moz(mytype, handler) {
mytype.DEFMETHOD("to_mozilla_ast", function() {
return set_moz_loc(this, handler(this));
});
}
};
function to_moz(node) {
return node != null ? node.to_mozilla_ast() : null;
}
};
function to_moz_block(node) {
return {
type: "BlockStatement",
body: node.body.map(to_moz)
};
}
};
function to_moz_scope(type, node) {
var body = node.body.map(to_moz);
@@ -635,5 +607,5 @@
type: type,
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.
https://github.com/mishoo/UglifyJS
https://github.com/mishoo/UglifyJS2
-------------------------------- (C) ---------------------------------
@@ -43,137 +43,115 @@
"use strict";
function find_builtins(reserved) {
function find_builtins() {
// NaN will be included due to Number.NaN
[
var a = [
"null",
"true",
"false",
"Infinity",
"-Infinity",
"undefined",
].forEach(add);
[
Array,
Boolean,
Date,
Error,
Function,
Math,
Number,
Object,
RegExp,
String,
].forEach(function(ctor) {
];
[ Object, Array, Function, Number,
String, Boolean, Error, Math,
Date, RegExp
].forEach(function(ctor){
Object.getOwnPropertyNames(ctor).map(add);
if (ctor.prototype) {
Object.getOwnPropertyNames(ctor.prototype).map(add);
}
});
function add(name) {
push_uniq(reserved, name);
push_uniq(a, name);
}
}
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;
}));
return a;
}
function mangle_properties(ast, options) {
options = defaults(options, {
builtins: false,
cache: null,
debug: false,
keep_quoted: false,
ignore_quoted: false,
only_cache: false,
regex: null,
reserved: null,
}, true);
});
var reserved = options.reserved;
if (!Array.isArray(reserved)) reserved = [];
if (!options.builtins) find_builtins(reserved);
if (reserved == null)
reserved = find_builtins();
var cname = -1;
var cache;
if (options.cache) {
cache = options.cache.props;
cache.each(function(mangled_name) {
push_uniq(reserved, mangled_name);
});
} else {
cache = new Dictionary();
var cache = options.cache;
if (cache == null) {
cache = {
cname: -1,
props: new Dictionary()
};
}
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 may be enabled as an empty string, which is falsey. Also treat passing 'true'
// the same as passing an empty string.
var debug = options.debug !== false;
var debug_suffix;
if (debug) debug_suffix = options.debug === true ? "" : options.debug;
var debug = (options.debug !== false);
var debug_name_suffix;
if (debug) {
debug_name_suffix = (options.debug === true ? "" : options.debug);
}
var names_to_mangle = [];
var unmangleable = [];
var ignored = {};
// step 1: find candidates to mangle
ast.walk(new TreeWalker(function(node) {
ast.walk(new TreeWalker(function(node){
if (node instanceof AST_ObjectKeyVal) {
add(node.key);
} else if (node instanceof AST_ObjectProperty) {
add(node.key, ignore_quoted && node.quote);
}
else if (node instanceof AST_ObjectProperty) {
// setter or getter, since KeyVal is handled above
add(node.key.name);
} else if (node instanceof AST_Dot) {
}
else if (node instanceof AST_Dot) {
add(node.property);
} else if (node instanceof AST_Sub) {
addStrings(node.property, add);
} else if (node instanceof AST_Call
&& node.expression.print_to_string() == "Object.defineProperty") {
addStrings(node.args[1], add);
}
else if (node instanceof AST_Sub) {
addStrings(node.property, ignore_quoted);
}
}));
// 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) {
node.key = mangle(node.key);
} else if (node instanceof AST_ObjectProperty) {
if (!(ignore_quoted && node.quote))
node.key = mangle(node.key);
}
else if (node instanceof AST_ObjectProperty) {
// setter or getter
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
@@ -181,54 +159,106 @@ function mangle_properties(ast, options) {
function can_mangle(name) {
if (unmangleable.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;
return true;
}
function should_mangle(name) {
if (ignore_quoted && name in ignored) return false;
if (regex && !regex.test(name)) 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) {
if (can_mangle(name)) push_uniq(names_to_mangle, name);
if (!should_mangle(name)) push_uniq(unmangleable, name);
function add(name, ignore) {
if (ignore) {
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) {
if (!should_mangle(name)) {
return name;
}
var mangled = cache.get(name);
var mangled = cache.props.get(name);
if (!mangled) {
if (debug) {
// debug mode: use a prefix and suffix to preserve readability, e.g. o.foo -> o._$foo$NNN_.
var debug_mangled = "_$" + name + "$" + debug_suffix + "_";
if (can_mangle(debug_mangled)) mangled = debug_mangled;
var debug_mangled = "_$" + name + "$" + debug_name_suffix + "_";
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
if (!mangled) do {
mangled = base54(++cname);
} while (!can_mangle(mangled));
cache.set(name, mangled);
if (!mangled) {
// note can_mangle() does not check if the name collides with the 'ignored' set
// (filled with quoted properties when ignore_quoted set). Make sure we add this
// 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;
}
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) {
return node.transform(new TreeTransformer(function(node) {
if (node instanceof AST_Sequence) {
var last = node.expressions.length - 1;
node.expressions[last] = mangleStrings(node.expressions[last]);
} else if (node instanceof AST_String) {
return node.transform(new TreeTransformer(function(node){
if (node instanceof AST_Seq) {
node.cdr = mangleStrings(node.cdr);
}
else if (node instanceof AST_String) {
node.value = mangle(node.value);
} else if (node instanceof AST_Conditional) {
}
else if (node instanceof AST_Conditional) {
node.consequent = mangleStrings(node.consequent);
node.alternative = mangleStrings(node.alternative);
}
return node;
}));
}
}

View File

@@ -1,7 +1,7 @@
/***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS
https://github.com/mishoo/UglifyJS2
-------------------------------- (C) ---------------------------------
@@ -43,62 +43,65 @@
"use strict";
function SymbolDef(id, scope, orig, init) {
this.eliminated = 0;
this.global = false;
this.id = id;
this.init = init;
this.lambda = orig instanceof AST_SymbolLambda;
this.mangled_name = null;
function SymbolDef(scope, index, orig) {
this.name = orig.name;
this.orig = [ orig ];
this.references = [];
this.replaced = 0;
this.scope = scope;
this.references = [];
this.global = false;
this.mangled_name = null;
this.undeclared = false;
}
this.index = index;
this.id = SymbolDef.next_id++;
};
SymbolDef.next_id = 1;
SymbolDef.prototype = {
unmangleable: function(options) {
return this.global && !options.toplevel
if (!options) options = {};
return (this.global && !options.toplevel)
|| this.undeclared
|| !options.eval && this.scope.pinned()
|| options.keep_fnames
|| (!options.eval && (this.scope.uses_eval || this.scope.uses_with))
|| (options.keep_fnames
&& (this.orig[0] instanceof AST_SymbolLambda
|| this.orig[0] instanceof AST_SymbolDefun);
|| this.orig[0] instanceof AST_SymbolDefun));
},
mangle: function(options) {
var cache = options.cache && options.cache.props;
if (this.global && cache && cache.has(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;
if (def = this.redefined()) {
if (this.defun && (def = this.defun.variables.get(this.name))) {
this.mangled_name = def.mangled_name || def.name;
} else {
this.mangled_name = next_mangled_name(this.scope, options, this);
}
} else
this.mangled_name = s.next_mangled(options, this);
if (this.global && cache) {
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, {
cache: null,
ie8: false,
screw_ie8: true,
});
// pass 1: setup scope chaining and handle definitions
var self = this;
var scope = self.parent_scope = null;
var labels = new Dictionary();
var defun = null;
var tw = new TreeWalker(function(node, descend) {
var tw = new TreeWalker(function(node, descend){
if (node instanceof AST_Catch) {
var save_scope = scope;
scope = new AST_Scope(node);
@@ -111,14 +114,28 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
node.init_scope_vars(scope);
var save_scope = scope;
var save_defun = defun;
var save_labels = labels;
defun = scope = node;
labels = new Dictionary();
descend();
scope = save_scope;
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) {
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;
}
if (node instanceof AST_Symbol) {
@@ -128,130 +145,109 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
node.thedef = node;
node.references = [];
}
if (node instanceof AST_SymbolDefun) {
// This should be defined in the parent scope, as we encounter the
// AST_Defun node before getting to its AST_Symbol.
(node.scope = defun.parent_scope.resolve()).def_function(node, defun);
} else if (node instanceof AST_SymbolLambda) {
var def = defun.def_function(node, node.name == "arguments" ? undefined : defun);
if (options.ie8) def.defun = defun.parent_scope.resolve();
} else if (node instanceof AST_SymbolVar) {
defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
if (node instanceof AST_SymbolLambda) {
defun.def_function(node);
}
else if (node instanceof AST_SymbolDefun) {
// Careful here, the scope where this should be defined is
// the parent scope. The reason is that we enter a new
// scope when we encounter the AST_Defun node (which is
// instanceof AST_Scope) but we get to the symbol a bit
// 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) {
node.mark_enclosed(options);
var def = scope.find_variable(node);
if (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;
}
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);
// pass 2: find back references and eval
self.globals = new Dictionary();
var tw = new TreeWalker(function(node) {
if (node instanceof AST_LoopControl) {
if (node.label) node.label.thedef.references.push(node);
var func = null;
var globals = self.globals = new Dictionary();
var tw = new TreeWalker(function(node, descend){
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;
}
if (node instanceof AST_SymbolRef) {
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);
if (node.scope instanceof AST_Lambda && name == "arguments") {
node.scope.uses_arguments = true;
}
if (!sym) {
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.reference(options);
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);
// pass 3: fix up any scoping issue with IE8
if (options.ie8) self.walk(new TreeWalker(function(node) {
if (node instanceof AST_SymbolCatch) {
var scope = node.thedef.defun;
if (scope.name instanceof AST_SymbolLambda && scope.name.name == node.name) {
scope = scope.parent_scope.resolve();
if (!options.screw_ie8) {
self.walk(new TreeWalker(function(node, descend) {
if (node instanceof AST_SymbolCatch) {
var name = node.name;
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) {
var name = node.name;
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);
if (options.cache) {
this.cname = options.cache.cname;
}
});
AST_Scope.DEFMETHOD("make_def", function(orig, init) {
var top = this;
while (top.parent_scope) top = top.parent_scope;
return new SymbolDef(++top.next_def_id, this, orig, init);
});
AST_Toplevel.DEFMETHOD("def_global", function(node) {
AST_Toplevel.DEFMETHOD("def_global", function(node){
var globals = this.globals, name = node.name;
if (globals.has(name)) {
return globals.get(name);
} else {
var g = this.make_def(node);
var g = new SymbolDef(this, globals.size(), node);
g.undeclared = true;
g.global = true;
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.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
@@ -269,10 +265,10 @@ AST_Scope.DEFMETHOD("init_scope_vars", function(parent_scope) {
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);
this.uses_arguments = false;
this.def_variable(new AST_SymbolFunarg({
this.def_variable(new AST_SymbolVar({
name: "arguments",
start: this.start,
end: this.end
@@ -281,7 +277,8 @@ AST_Lambda.DEFMETHOD("init_scope_vars", function() {
AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
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);
if (options.keep_fnames) {
s.functions.each(function(d) {
@@ -289,6 +286,7 @@ AST_Symbol.DEFMETHOD("mark_enclosed", function(options) {
});
}
if (s === def.scope) break;
s = s.parent_scope;
}
});
@@ -297,338 +295,362 @@ AST_Symbol.DEFMETHOD("reference", function(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;
return this.variables.get(name)
|| (this.parent_scope && this.parent_scope.find_variable(name));
});
AST_Scope.DEFMETHOD("def_function", function(symbol, init) {
var def = this.def_variable(symbol, init);
if (!def.init || def.init instanceof AST_Defun) def.init = init;
this.functions.set(symbol.name, def);
return def;
AST_Scope.DEFMETHOD("def_function", function(symbol){
this.functions.set(symbol.name, this.def_variable(symbol));
});
AST_Scope.DEFMETHOD("def_variable", function(symbol, init) {
var def = this.variables.get(symbol.name);
if (def) {
def.orig.push(symbol);
if (def.init instanceof AST_Function) def.init = init;
} else {
def = this.make_def(symbol, init);
AST_Scope.DEFMETHOD("def_variable", function(symbol){
var def;
if (!this.variables.has(symbol.name)) {
def = new SymbolDef(this, this.variables.size(), symbol);
this.variables.set(symbol.name, def);
def.global = !this.parent_scope;
} else {
def = this.variables.get(symbol.name);
def.orig.push(symbol);
}
return symbol.thedef = def;
});
AST_Lambda.DEFMETHOD("resolve", return_this);
AST_Scope.DEFMETHOD("resolve", function() {
return this.parent_scope.resolve();
AST_Scope.DEFMETHOD("next_mangled", function(options){
var ext = this.enclosed;
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) {
var names = scope.names_in_use;
if (!names) {
scope.names_in_use = names = Object.create(scope.mangled_names || null);
scope.cname_holes = [];
var cache = options.cache && options.cache.props;
scope.enclosed.forEach(function(def) {
if (def.unmangleable(options)) names[def.name] = true;
if (def.global && cache && cache.has(def.name)) {
names[cache.get(def.name)] = true;
}
});
}
return names;
}
AST_Function.DEFMETHOD("next_mangled", function(options, def){
// #179, #326
// in Safari strict mode, something like (function x(x){...}) is a syntax error;
// a function expression's argument cannot shadow the function expression's name
var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition();
// the function's mangled_name is null when keep_fnames is true
var tricky_name = tricky_def ? tricky_def.mangled_name || tricky_def.name : null;
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) {
name = base54(++scope.cname);
if (in_use[name] || RESERVED_WORDS[name] || options.reserved.has[name]) continue;
if (!names[name]) break;
holes.push(scope.cname);
var name = AST_Lambda.prototype.next_mangled.call(this, options, def);
if (!tricky_name || tricky_name != name)
return name;
}
scope.names_in_use[name] = true;
return name;
}
});
AST_Symbol.DEFMETHOD("unmangleable", function(options) {
var def = this.definition();
return !def || def.unmangleable(options);
AST_Symbol.DEFMETHOD("unmangleable", function(options){
return this.definition().unmangleable(options);
});
// labels are always mangleable
AST_Label.DEFMETHOD("unmangleable", return_false);
AST_Symbol.DEFMETHOD("unreferenced", function() {
return !this.definition().references.length && !this.scope.pinned();
AST_Label.DEFMETHOD("unmangleable", function(){
return false;
});
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;
});
AST_Symbol.DEFMETHOD("global", function() {
AST_Symbol.DEFMETHOD("global", function(){
return this.definition().global;
});
function _default_mangler_options(options) {
options = defaults(options, {
AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options){
return defaults(options, {
eval : false,
ie8 : false,
except : [],
keep_fnames : false,
reserved : [],
screw_ie8 : true,
sort : false, // Ignored. Flag retained for backwards compatibility.
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) {
options = _default_mangler_options(options);
AST_Toplevel.DEFMETHOD("mangle_names", function(options){
options = this._default_mangler_options(options);
// Never mangle arguments
options.except.push('arguments');
// We only need to mangle declaration nodes. Special logic wired
// 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
// the AST_SymbolDeclaration that it points to).
var lname = -1;
var to_mangle = [];
if (options.cache && options.cache.props) {
var mangled_names = this.mangled_names = Object.create(null);
options.cache.props.each(function(mangled_name) {
mangled_names[mangled_name] = true;
if (options.cache) {
this.globals.each(function(symbol){
if (options.except.indexOf(symbol.name) < 0) {
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) {
// lname is incremented when we get to the AST_Label
var save_nesting = lname;
descend();
lname = save_nesting;
return true;
return true; // don't descend again in TreeWalker
}
if (node instanceof AST_Scope) {
descend();
if (options.cache && node instanceof AST_Toplevel) {
node.globals.each(mangle);
}
if (node instanceof AST_Defun && tw.has_directive("use asm")) {
var sym = new AST_SymbolRef(node.name);
sym.scope = node;
sym.reference(options);
}
node.variables.each(function(def) {
if (!defer_redef(def)) mangle(def);
var p = tw.parent(), a = [];
node.variables.each(function(symbol){
if (options.except.indexOf(symbol.name) < 0) {
a.push(symbol);
}
});
return true;
to_mangle.push.apply(to_mangle, a);
return;
}
if (node instanceof AST_Label) {
var name;
do {
name = base54(++lname);
} while (RESERVED_WORDS[name]);
do name = base54(++lname); while (!is_identifier(name));
node.mangled_name = name;
return true;
}
if (!options.ie8 && node instanceof AST_Catch) {
var def = node.argname.definition();
var redef = defer_redef(def, node.argname);
descend();
if (!redef) mangle(def);
return true;
if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
to_mangle.push(node.definition());
return;
}
});
this.walk(tw);
redefined.forEach(mangle);
to_mangle.forEach(function(def){ def.mangle(options) });
function mangle(def) {
if (options.reserved.has[def.name]) return;
def.mangle(options);
if (options.cache) {
options.cache.cname = this.cname;
}
});
function defer_redef(def, node) {
var redef = def.redefined();
if (!redef) return false;
redefined.push(def);
def.references.forEach(reference);
if (node) reference(node);
return true;
function reference(sym) {
sym.thedef = redef;
sym.reference(options);
sym.thedef = def;
AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options){
options = this._default_mangler_options(options);
var tw = new TreeWalker(function(node){
if (node instanceof AST_Constant)
base54.consider(node.print_to_string());
else if (node instanceof AST_Return)
base54.consider("return");
else if (node instanceof AST_Throw)
base54.consider("throw");
else if (node instanceof AST_Continue)
base54.consider("continue");
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");
}
}
});
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
var cache = options.cache && options.cache.props;
var avoid = Object.create(null);
options.reserved.forEach(to_avoid);
this.globals.each(add_def);
this.walk(new TreeWalker(function(node) {
if (node instanceof AST_Scope) node.variables.each(add_def);
if (node instanceof AST_SymbolCatch) add_def(node.definition());
}));
return avoid;
function to_avoid(name) {
avoid[name] = true;
}
function add_def(def) {
var name = def.name;
if (def.global && cache && cache.has(name)) name = cache.get(name);
else if (!def.unmangleable(options)) return;
to_avoid(name);
}
});
AST_Toplevel.DEFMETHOD("expand_names", function(options) {
base54.reset();
else if (node instanceof AST_Var)
base54.consider("var");
else if (node instanceof AST_Const)
base54.consider("const");
else if (node instanceof AST_Lambda)
base54.consider("function");
else if (node instanceof AST_For)
base54.consider("for");
else if (node instanceof AST_ForIn)
base54.consider("for in");
else if (node instanceof AST_Switch)
base54.consider("switch");
else if (node instanceof AST_Case)
base54.consider("case");
else if (node instanceof AST_Default)
base54.consider("default");
else if (node instanceof AST_With)
base54.consider("with");
else if (node instanceof AST_ObjectSetter)
base54.consider("set" + node.key);
else if (node instanceof AST_ObjectGetter)
base54.consider("get" + node.key);
else if (node instanceof AST_ObjectKeyVal)
base54.consider(node.key);
else if (node instanceof AST_New)
base54.consider("new");
else if (node instanceof AST_This)
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();
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 freq = Object.create(null);
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 string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
var chars, frequency;
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;) {
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() {
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;
reset();
base54.get = function(){ return chars };
base54.freq = function(){ return frequency };
function base54(num) {
var ret = "", base = 54;
num++;
do {
num--;
ret += chars[num % base];
ret += String.fromCharCode(chars[num % base]);
num = Math.floor(num / base);
base = 64;
} while (num > 0);
return ret;
}
};
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.
https://github.com/mishoo/UglifyJS
https://github.com/mishoo/UglifyJS2
-------------------------------- (C) ---------------------------------
@@ -43,149 +43,55 @@
"use strict";
var vlq_char = characters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
var vlq_bits = vlq_char.reduce(function(map, ch, bits) {
map[ch] = bits;
return map;
}, Object.create(null));
function vlq_decode(indices, str) {
var value = 0;
var shift = 0;
for (var i = 0, j = 0; i < str.length; i++) {
var bits = vlq_bits[str[i]];
value += (bits & 31) << shift;
if (bits & 32) {
shift += 5;
} else {
indices[j++] += value & 1 ? 0x80000000 | -(value >> 1) : value >> 1;
value = shift = 0;
}
}
return j;
}
function vlq_encode(num) {
var result = "";
num = Math.abs(num) << 1 | num >>> 31;
do {
var bits = num & 31;
if (num >>>= 5) bits |= 32;
result += vlq_char[bits];
} while (num);
return result;
}
function create_array_map() {
var map = Object.create(null);
var array = [];
array.index = function(name) {
if (!HOP(map, name)) {
map[name] = array.length;
array.push(name);
}
return map[name];
};
return array;
}
// a small wrapper around fitzgen's source-map library
function SourceMap(options) {
var sources = create_array_map();
var sources_content = options.includeSources && Object.create(null);
var names = create_array_map();
var mappings = "";
if (options.orig) Object.keys(options.orig).forEach(function(name) {
var map = options.orig[name];
var indices = [ 0, 0, 1, 0, 0 ];
options.orig[name] = {
names: map.names,
mappings: map.mappings.split(/;/).map(function(line) {
indices[0] = 0;
return line.split(/,/).map(function(segment) {
return indices.slice(0, vlq_decode(indices, segment));
});
}),
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;
}
options = defaults(options, {
file : null,
root : null,
orig : null,
orig_line_diff : 0,
dest_line_diff : 0,
});
var prev_source;
var generated_line = 1;
var generated_column = 0;
var source_index = 0;
var original_line = 1;
var original_column = 0;
var name_index = 0;
return {
add: options.orig ? function(source, gen_line, gen_col, orig_line, orig_col, name) {
var map = options.orig[source];
if (map) {
var segments = map.mappings[orig_line - 1];
if (!segments) return;
var indices;
for (var i = 0; i < segments.length; i++) {
var col = segments[i][0];
if (orig_col >= col) indices = segments[i];
if (orig_col <= col) break;
}
if (!indices || indices.length < 4) {
source = null;
} else {
source = map.sources[indices[1]];
orig_line = indices[2];
orig_col = indices[3];
if (indices.length > 4) name = map.names[indices[4]];
}
var generator = new MOZ_SourceMap.SourceMapGenerator({
file : options.file,
sourceRoot : options.root
});
var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
if (orig_map && Array.isArray(options.orig.sources)) {
orig_map._sources.toArray().forEach(function(source) {
var sourceContent = orig_map.sourceContentFor(source, true);
if (sourceContent) {
generator.setSourceContent(source, sourceContent);
}
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) {
if (prev_source == null && source == null) return;
prev_source = source;
if (generated_line < gen_line) {
generated_column = 0;
do {
mappings += ";";
} while (++generated_line < gen_line);
} else if (mappings) {
mappings += ",";
if (orig_map) {
var info = orig_map.originalPositionFor({
line: orig_line,
column: orig_col
});
if (info.source === null) {
return;
}
source = info.source;
orig_line = info.line;
orig_col = info.column;
name = info.name || name;
}
mappings += vlq_encode(gen_col - generated_column);
generated_column = gen_col;
if (source == null) return;
var src_idx = sources.index(source);
mappings += vlq_encode(src_idx - source_index);
source_index = src_idx;
mappings += vlq_encode(orig_line - original_line);
original_line = orig_line;
mappings += vlq_encode(orig_col - original_column);
original_column = orig_col;
if (options.names && name != null) {
var name_idx = names.index(name);
mappings += vlq_encode(name_idx - name_index);
name_index = name_idx;
}
}
}
generator.addMapping({
generated : { line: gen_line + options.dest_line_diff, column: gen_col },
original : { line: orig_line + options.orig_line_diff, column: orig_col },
source : source,
name : name
});
};
return {
add : add,
get : function() { return generator },
toString : function() { return JSON.stringify(generator.toJSON()); }
};
};

View File

@@ -1,7 +1,7 @@
/***********************************************************************
A JavaScript tokenizer / parser / beautifier / compressor.
https://github.com/mishoo/UglifyJS
https://github.com/mishoo/UglifyJS2
-------------------------------- (C) ---------------------------------
@@ -43,6 +43,8 @@
"use strict";
// Tree transformer helpers.
function TreeTransformer(before, after) {
TreeWalker.call(this);
this.before = before;
@@ -50,136 +52,167 @@ function TreeTransformer(before, after) {
}
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) {
return List(list, function(node) {
return MAP(list, function(node){
return node.transform(tw, true);
});
}
};
DEF(AST_Node, noop);
DEF(AST_LabeledStatement, function(self, tw) {
_(AST_Node, noop);
_(AST_LabeledStatement, function(self, tw){
self.label = self.label.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);
});
DEF(AST_Block, function(self, tw) {
_(AST_Block, function(self, tw){
self.body = do_list(self.body, tw);
});
DEF(AST_Do, function(self, tw) {
self.body = self.body.transform(tw);
self.condition = self.condition.transform(tw);
});
DEF(AST_While, function(self, tw) {
_(AST_DWLoop, function(self, tw){
self.condition = self.condition.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.condition) self.condition = self.condition.transform(tw);
if (self.step) self.step = self.step.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.object = self.object.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.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);
});
DEF(AST_LoopControl, function(self, tw) {
_(AST_LoopControl, function(self, 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.body = self.body.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.body = do_list(self.body, tw);
});
DEF(AST_Case, function(self, tw) {
_(AST_Case, function(self, tw){
self.expression = self.expression.transform(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);
if (self.bcatch) self.bcatch = self.bcatch.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.body = do_list(self.body, tw);
});
DEF(AST_Definitions, function(self, tw) {
_(AST_Definitions, function(self, 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);
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);
self.argnames = do_list(self.argnames, 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.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);
});
DEF(AST_Sub, function(self, tw) {
_(AST_Sub, function(self, tw){
self.expression = self.expression.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);
});
DEF(AST_Binary, function(self, tw) {
_(AST_Binary, function(self, tw){
self.left = self.left.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.consequent = self.consequent.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);
});
DEF(AST_Object, function(self, tw) {
_(AST_Object, function(self, 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);
});
})(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.
https://github.com/mishoo/UglifyJS
https://github.com/mishoo/UglifyJS2
-------------------------------- (C) ---------------------------------
@@ -43,25 +43,40 @@
"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) {
return str.split("");
}
};
function member(name, array) {
return array.indexOf(name) >= 0;
}
};
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) {
if (i <= 0) return "";
if (i == 1) return str;
var d = repeat_string(str, i >> 1);
d += d;
return i & 1 ? d + str : d;
}
if (i & 1) d += str;
return d;
};
function configure_error_stack(fn) {
Object.defineProperty(fn.prototype, "stack", {
@@ -70,7 +85,7 @@ function configure_error_stack(fn) {
err.name = this.name;
try {
throw err;
} catch (e) {
} catch(e) {
return e.stack;
}
}
@@ -80,21 +95,27 @@ function configure_error_stack(fn) {
function DefaultsError(msg, defs) {
this.message = msg;
this.defs = defs;
}
};
DefaultsError.prototype = Object.create(Error.prototype);
DefaultsError.prototype.constructor = DefaultsError;
DefaultsError.prototype.name = "DefaultsError";
configure_error_stack(DefaultsError);
DefaultsError.croak = function(msg, defs) {
throw new DefaultsError(msg, defs);
};
function defaults(args, defs, croak) {
if (croak) for (var i in args) {
if (HOP(args, i) && !HOP(defs, i)) throw new DefaultsError("`" + i + "` is not a supported option", defs);
if (args === true)
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) {
if (HOP(args, i)) defs[i] = args[i];
}
return defs;
}
return ret;
};
function merge(obj, ext) {
var count = 0;
@@ -103,7 +124,7 @@ function merge(obj, ext) {
count++;
}
return count;
}
};
function noop() {}
function return_false() { return false; }
@@ -111,8 +132,8 @@ function return_true() { return true; }
function return_this() { return this; }
function return_null() { return null; }
var List = (function() {
function List(a, f, backwards) {
var MAP = (function(){
function MAP(a, f, backwards) {
var ret = [], top = [], i;
function doit() {
var val = f(a[i], i);
@@ -125,7 +146,8 @@ var List = (function() {
} else {
top.push(val);
}
} else if (val !== skip) {
}
else if (val !== skip) {
if (val instanceof Splice) {
ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
} else {
@@ -133,8 +155,8 @@ var List = (function() {
}
}
return is_last;
}
if (Array.isArray(a)) {
};
if (a instanceof Array) {
if (backwards) {
for (i = a.length; --i >= 0;) if (doit()) break;
ret.reverse();
@@ -142,59 +164,132 @@ var List = (function() {
} else {
for (i = 0; i < a.length; ++i) if (doit()) break;
}
} else {
}
else {
for (i in a) if (HOP(a, i)) if (doit()) break;
}
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); };
List.splice = function(val) { return new Splice(val); };
List.last = function(val) { return new Last(val); };
var skip = List.skip = {};
function AtTop(val) { this.v = val; }
function Splice(val) { this.v = val; }
function Last(val) { this.v = val; }
return List;
MAP.at_top = function(val) { return new AtTop(val) };
MAP.splice = function(val) { return new Splice(val) };
MAP.last = function(val) { return new Last(val) };
var skip = MAP.skip = {};
function AtTop(val) { this.v = val };
function Splice(val) { this.v = val };
function Last(val) { this.v = val };
return MAP;
})();
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) {
return text.replace(/\{(.+?)\}/g, function(str, p) {
return text.replace(/\{(.+?)\}/g, function(str, p){
return props && props[p];
});
}
};
function remove(array, el) {
var index = array.indexOf(el);
if (index >= 0) array.splice(index, 1);
}
for (var i = array.length; --i >= 0;) {
if (array[i] === el) array.splice(i, 1);
}
};
function makePredicate(words) {
if (!Array.isArray(words)) words = words.split(" ");
var map = Object.create(null);
words.forEach(function(word) {
map[word] = true;
function mergeSort(array, cmp) {
if (array.length < 2) return array.slice();
function merge(a, b) {
var r = [], ai = 0, bi = 0, i = 0;
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) {
for (var i = array.length; --i >= 0;)
if (!predicate(array[i], i))
if (!predicate(array[i]))
return false;
return true;
}
};
function Dictionary() {
this._values = Object.create(null);
this._size = 0;
}
};
Dictionary.prototype = {
set: function(key, val) {
if (!this.has(key)) ++this._size;
@@ -218,12 +313,6 @@ Dictionary.prototype = {
return this;
},
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) {
for (var i in this._values)
f(this._values[i], i.substr(1));
@@ -237,13 +326,6 @@ Dictionary.prototype = {
ret.push(f(this._values[i], i.substr(1)));
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 }
};
Dictionary.fromObject = function(obj) {
@@ -261,22 +343,20 @@ function HOP(obj, prop) {
// a statement.
function first_in_statement(stack) {
var node = stack.parent(-1);
for (var i = 0, p; p = stack.parent(i++); node = p) {
if (p.TYPE == "Call") {
if (p.expression === node) continue;
} else if (p instanceof AST_Binary) {
if (p.left === node) continue;
} else if (p instanceof AST_Conditional) {
if (p.condition === node) continue;
} else if (p instanceof AST_PropAccess) {
if (p.expression === node) continue;
} else if (p instanceof AST_Sequence) {
if (p.expressions[0] === node) continue;
} else if (p instanceof AST_Statement) {
return p.body === node;
} else if (p instanceof AST_UnaryPostfix) {
if (p.expression === node) continue;
for (var i = 0, p; p = stack.parent(i); i++) {
if (p instanceof AST_Statement && p.body === node)
return true;
if ((p instanceof AST_Seq && p.car === node ) ||
(p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) ) ||
(p instanceof AST_Dot && p.expression === node ) ||
(p instanceof AST_Sub && p.expression === node ) ||
(p instanceof AST_Conditional && p.condition === node ) ||
(p instanceof AST_Binary && p.left === node ) ||
(p instanceof AST_UnaryPostfix && p.expression === node ))
{
node = p;
} else {
return false;
}
return false;
}
}

View File

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

View File

@@ -4,45 +4,43 @@
"use strict";
var createHash = require("crypto").createHash;
var fetch = require("./fetch");
var spawn = require("child_process").spawn;
var zlib = require("zlib");
var fork = require("child_process").fork;
var args = process.argv.slice(2);
if (!args.length) args.push("-mc");
args.unshift("bin/uglifyjs");
args.push("--timings");
if (!args.length) {
args.push("-mc", "warnings=false");
}
args.push("--stats");
var urls = [
"https://code.jquery.com/jquery-3.4.1.js",
"https://code.angularjs.org/1.7.8/angular.js",
"https://unpkg.com/mathjs@6.2.3/dist/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://code.jquery.com/jquery-3.2.1.js",
"https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.4/angular.js",
"https://cdnjs.cloudflare.com/ajax/libs/mathjs/3.9.0/math.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://cdnjs.cloudflare.com/ajax/libs/ember.js/2.12.2/ember.prod.js",
"https://raw.githubusercontent.com/kangax/html-minifier/v4.0.0/dist/htmlminifier.js",
"https://unpkg.com/react@15.3.2/dist/react.js",
"http://builds.emberjs.com/tags/v2.11.0/ember.prod.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 remaining = 2 * urls.length;
function done() {
if (!--remaining) {
var failures = [];
var sum = { input: 0, output: 0, gzip: 0 };
urls.forEach(function(url) {
var info = results[url];
console.log();
console.log(url);
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("Uglified:", info.output, "bytes");
console.log("GZipped: ", info.gzip, "bytes");
console.log("SHA1 sum:", info.sha1);
if (info.code) {
failures.push(url);
}
sum.input += info.input;
sum.output += info.output;
sum.gzip += info.gzip;
});
if (failures.length) {
console.error("Benchmark failed:");
@@ -50,13 +48,6 @@ function done() {
console.error(url);
});
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] = {
input: 0,
output: 0,
gzip: 0,
log: ""
};
fetch(url, function(err, res) {
if (err) throw err;
var uglifyjs = spawn(process.argv[0], args, { silent: true });
require(url.slice(0, url.indexOf(":"))).get(url, function(res) {
var uglifyjs = fork("bin/uglifyjs", args, { silent: true });
res.on("data", function(data) {
results[url].input += data.length;
}).pipe(uglifyjs.stdin);
var sha1 = createHash("sha1");
uglifyjs.stdout.on("data", function(data) {
results[url].output += data.length;
}).pipe(zlib.createGzip({
level: zlib.Z_BEST_COMPRESSION
})).on("data", function(data) {
results[url].gzip += data.length;
sha1.update(data);
}).on("end", function() {
results[url].sha1 = sha1.digest("hex");
}).pipe(createHash("sha1")).on("data", function(data) {
results[url].sha1 = data.toString("hex");
done();
});
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: {
options = {
evaluate: true,
strings: true,
unsafe: true,
}
unsafe : true,
evaluate : true
};
input: {
var a = [ "foo", "bar", "baz" ].join("");
var a1 = [ "foo", "bar", "baz" ].join();
@@ -65,10 +64,9 @@ constant_join: {
constant_join_2: {
options = {
evaluate: true,
strings: true,
unsafe: true,
}
unsafe : true,
evaluate : true
};
input: {
var a = [ "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: {
options = {
evaluate: true,
strings: true,
unsafe: true,
}
evaluate: true,
};
input: {
var foo, bar, baz;
var a = [ null ].join();
var b = [ , ].join();
var c = [ , 1, , 3 ].join();
@@ -115,7 +111,6 @@ constant_join_3: {
var l = [ foo, bar + "baz" ].join("");
}
expect: {
var foo, bar, baz;
var a = "";
var b = "";
var c = ",1,,3";
@@ -133,224 +128,50 @@ constant_join_3: {
for_loop: {
options = {
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unsafe: true,
unused: true,
}
unsafe : true,
unused : true,
evaluate : true,
reduce_vars : true
};
input: {
function f0() {
var a = [1, 2, 3];
var b = 0;
for (var i = 0; i < a.length; i++)
b += a[i];
return b;
for (var i = 0; i < a.length; i++) {
console.log(a[i]);
}
}
function f1() {
var a = [1, 2, 3];
var b = 0;
for (var i = 0, len = a.length; i < len; i++)
b += a[i];
return b;
for (var i = 0, len = a.length; i < len; i++) {
console.log(a[i]);
}
}
function f2() {
var a = [1, 2, 3];
for (var i = 0; i < a.length; i++)
for (var i = 0; i < a.length; i++) {
a[i]++;
return a[2];
}
}
console.log(f0(), f1(), f2());
}
expect: {
function f0() {
var a = [1, 2, 3];
var b = 0;
for (var i = 0; i < 3; i++)
b += a[i];
return b;
console.log(a[i]);
}
function f1() {
var a = [1, 2, 3];
var b = 0;
for (var i = 0; i < 3; i++)
b += a[i];
return b;
console.log(a[i]);
}
function f2() {
var a = [1, 2, 3];
for (var i = 0; i < a.length; 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 = {}
beautify = {
ascii_only : true,
ie8 : false,
screw_ie8 : true,
beautify : false,
}
input: {
@@ -13,14 +13,14 @@ ascii_only_true: {
"\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: {
options = {}
beautify = {
ascii_only : false,
ie8 : false,
screw_ie8 : true,
beautify : false,
}
input: {
@@ -31,5 +31,6 @@ ascii_only_false: {
"\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: {
options = {
assignments: true,
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
drop_debugger: true,
evaluate: true,
hoist_funs: true,
hoist_vars: true,
if_return: true,
join_vars: true,
keep_fargs: true,
keep_fnames: false,
loops: true,
negate_iife: true,
properties: true,
sequences: true,
side_effects: true,
unused: true,
}
sequences : true,
properties : true,
dead_code : true,
drop_debugger : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
loops : true,
unused : true,
hoist_funs : true,
keep_fargs : true,
keep_fnames : false,
hoist_vars : true,
if_return : true,
join_vars : true,
cascade : true,
side_effects : true,
negate_iife : true
};
input: {
// adapted from http://asmjs.org/spec/latest/
function asm_GeometricMean(stdlib, foreign, buffer) {
@@ -91,11 +91,12 @@ asm_mixed: {
function no_asm_GeometricMean(stdlib, foreign, buffer) {
function logSum(start, end) {
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;
}
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);
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: {
options = {
assignments: true,
evaluate: true,
}
input: {
@@ -61,7 +60,6 @@ op_equals_left_local_var: {
op_equals_right_local_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
@@ -125,7 +123,6 @@ op_equals_right_local_var: {
}
op_equals_left_global_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
@@ -182,7 +179,6 @@ op_equals_left_global_var: {
op_equals_right_global_var: {
options = {
assignments: true,
evaluate: true,
}
input: {
@@ -240,224 +236,3 @@ op_equals_right_global_var: {
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: {
options = {
evaluate: true,
}
evaluate: true
};
input: {
var a = "foo" + "bar" + x() + "moo" + "foo" + y() + "x" + "y" + "z" + q();
var b = "foo" + 1 + x() + 2 + "boo";
@@ -21,14 +21,12 @@ concat_1: {
var c = 1 + x() + 2 + "boo";
var d = 1 + x() + 2 + 3 + "boo";
var e = 1 + x() + 2 + "X3boo";
var f = "\x00360\x008\0";
var f = "\x00360\08\0";
}
}
concat_2: {
options = {
strings: true,
}
options = {};
input: {
console.log(
1 + (2 + 3),
@@ -57,9 +55,7 @@ concat_2: {
}
concat_3: {
options = {
strings: true,
}
options = {};
input: {
console.log(
1 + 2 + (3 + 4 + 5),
@@ -88,9 +84,7 @@ concat_3: {
}
concat_4: {
options = {
strings: true,
}
options = {};
input: {
console.log(
1 + "2" + (3 + 4 + 5),
@@ -119,9 +113,7 @@ concat_4: {
}
concat_5: {
options = {
strings: true,
}
options = {};
input: {
console.log(
"1" + 2 + (3 + 4 + 5),
@@ -150,9 +142,7 @@ concat_5: {
}
concat_6: {
options = {
strings: true,
}
options = {};
input: {
console.log(
"1" + "2" + (3 + 4 + 5),
@@ -181,9 +171,6 @@ concat_6: {
}
concat_7: {
options = {
strings: true,
}
input: {
console.log(
"" + 1,
@@ -210,9 +197,6 @@ concat_7: {
}
concat_8: {
options = {
strings: true,
}
input: {
console.log(
1 + "",
@@ -237,20 +221,3 @@ concat_8: {
}
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: {
options = {
drop_debugger: false,
}
drop_debugger: false
};
input: {
debugger;
}
@@ -12,8 +12,8 @@ keep_debugger: {
drop_debugger: {
options = {
drop_debugger: true,
}
drop_debugger: true
};
input: {
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: {
options = {}
options = {};
input: {
console.log('foo');
console.log.apply(console, arguments);
@@ -11,9 +11,7 @@ drop_console_1: {
}
drop_console_2: {
options = {
drop_console: true,
}
options = { drop_console: true };
input: {
console.log('foo');
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 = {
global_defs: {
D: "foo bar",
},
}
}
input: {
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: {
options = {
global_defs: {
@@ -51,7 +37,6 @@ object: {
VALUE: 42,
},
},
side_effects: true,
unsafe: true,
}
input: {
@@ -135,7 +120,7 @@ mixed: {
properties: true,
}
input: {
var FOO = { BAR: 0 };
const FOO = { BAR: 0 };
console.log(FOO.BAR);
console.log(++CONFIG.DEBUG);
console.log(++CONFIG.VALUE);
@@ -145,7 +130,7 @@ mixed: {
console.log(CONFIG);
}
expect: {
var FOO = { BAR: 0 };
const FOO = { BAR: 0 };
console.log("moo");
console.log(++CONFIG.DEBUG);
console.log(++CONFIG.VALUE);
@@ -155,8 +140,9 @@ mixed: {
console.log(CONFIG);
}
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:7,8]",
'WARN: global_defs CONFIG.VALUE redefined [test/compress/global_defs.js:126,22]',
'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);
}
}
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: {
input: {
(function(a, b) {
console.log(a < !--b && a-- > b, a, b);
})(1, 2);
function f(a, b, x, y) { return a < !--b && x-- > y; }
}
expect_exact: "(function(a,b){console.log(a<! --b&&a-- >b,a,b)})(1,2);"
expect_stdout: "false 1 1"
expect_exact: "function f(a,b,x,y){return a< !--b&&x-- >y}";
}
html_comment_in_less_than: {
input: {
(function(a, b, c) {
console.log(
a < !--b,
a < !--b + c,
a + b < !--c,
a, b, c
);
})(1, 2, 3);
function f(a, b) { return a < !--b; }
}
expect_exact: "(function(a,b,c){console.log(a<! --b,a<! --b+c,a+b<! --c,a,b,c)})(1,2,3);"
expect_stdout: "false true false 1 0 2"
expect_exact: "function f(a,b){return a< !--b}";
}
html_comment_in_left_shift: {
input: {
(function(a, b, c) {
console.log(
a << !--b,
a << !--b + c,
a + b << !--c,
a, b, c
);
})(1, 2, 3);
function f(a, b) { return a << !--b; }
}
expect_exact: "(function(a,b,c){console.log(a<<! --b,a<<! --b+c,a+b<<! --c,a,b,c)})(1,2,3);"
expect_stdout: "1 16 1 1 0 2"
}
html_comment_in_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"
expect_exact: "function f(a,b){return a<< !--b}";
}
html_comment_in_right_shift: {
input: {
(function(a, b, c) {
console.log(
a-- >> b,
a-- >> b + c,
a + b-- >> c,
a, b, c
);
})(1, 2, 3);
function f(a, b) { return a-- >> b; }
}
expect_exact: "(function(a,b,c){console.log(a-- >>b,a-- >>b+c,a+b-- >>c,a,b,c)})(1,2,3);"
expect_stdout: "0 0 0 -1 1 3"
expect_exact: "function f(a,b){return a-- >>b}";
}
html_comment_in_zero_fill_right_shift: {
input: {
(function(a, b, c) {
console.log(
a-- >>> b,
a-- >>> b + c,
a + b-- >>> c,
a, b, c
);
})(1, 2, 3);
function f(a, b) { return a-- >>> b; }
}
expect_exact: "(function(a,b,c){console.log(a-- >>>b,a-- >>>b+c,a+b-- >>>c,a,b,c)})(1,2,3);"
expect_stdout: "0 0 0 -1 1 3"
expect_exact: "function f(a,b){return a-- >>>b}";
}
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: {
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_stdout: "42"
expect_exact: 'function f(){return"\\x3c!--HTML--\\x3ecomment in\\x3c!--string literal--\\x3e"}';
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,14 @@
if_return_1: {
options = {
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
}
input: {
function f(x) {
@@ -24,15 +24,15 @@ if_return_1: {
if_return_2: {
options = {
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
}
input: {
function f(x, y) {
@@ -49,15 +49,15 @@ if_return_2: {
if_return_3: {
options = {
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
}
input: {
function f(x) {
@@ -75,15 +75,15 @@ if_return_3: {
if_return_4: {
options = {
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
}
input: {
function f(x, y) {
@@ -100,15 +100,15 @@ if_return_4: {
if_return_5: {
options = {
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
}
input: {
function f() {
@@ -126,15 +126,15 @@ if_return_5: {
if_return_6: {
options = {
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
}
input: {
function f(x) {
@@ -150,15 +150,15 @@ if_return_6: {
if_return_7: {
options = {
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
}
input: {
function f(x) {
@@ -176,10 +176,10 @@ if_return_7: {
if_return_8: {
options = {
conditionals: true,
if_return: true,
sequences: true,
side_effects: true,
if_return: true,
sequences: true,
conditionals: true,
side_effects : true,
}
input: {
function f(e) {
@@ -220,15 +220,15 @@ if_return_8: {
issue_1089: {
options = {
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
if_return: true,
sequences: true,
side_effects: true,
unused: true,
if_return : true,
sequences : true,
conditionals : true,
comparisons : true,
evaluate : true,
booleans : true,
unused : true,
side_effects : true,
dead_code : true,
}
input: {
function x() {
@@ -243,7 +243,7 @@ issue_1089: {
expect: {
function x() {
var f = document.getElementById("fname");
if (12345 < f.files[0].size)
if (f.files[0].size > 12345)
return alert("alert"), f.focus(), !1;
}
}
@@ -251,9 +251,9 @@ issue_1089: {
issue_1437: {
options = {
conditionals: false,
if_return: true,
sequences: true,
if_return : true,
sequences : true,
conditionals : false
}
input: {
function x() {
@@ -281,9 +281,9 @@ issue_1437: {
issue_1437_conditionals: {
options = {
conditionals: true,
if_return: true,
sequences: true,
conditionals : true,
if_return : true,
sequences : true
}
input: {
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: {
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,
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true
}
input: {
function foo(x) {
@@ -30,35 +21,25 @@ non_hoisted_function_after_return: {
}
expect: {
function foo(x) {
return (x ? bar : baz)();
return x ? bar() : baz();
function bar() { return 7 }
function baz() { return 8 }
}
}
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:7,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:10,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:11,21]"
'WARN: Dropping unreachable code [test/compress/issue-1034.js:11,16]',
"WARN: Dropping unreachable code [test/compress/issue-1034.js:14,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:17,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:18,21]"
]
}
non_hoisted_function_after_return_2a: {
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,
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true,
collapse_vars: false, passes: 2, warnings: "verbose"
}
input: {
function foo(x) {
@@ -84,37 +65,26 @@ non_hoisted_function_after_return_2a: {
}
}
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:4,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:4,16]",
"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 unused variable a [test/compress/issue-1034.js:4,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:11,21]",
"INFO: pass 0: last_count: Infinity, count: 36",
"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:12,12]",
"INFO: Dropping unused variable b [test/compress/issue-1034.js:7,20]",
"INFO: Dropping unused variable c [test/compress/issue-1034.js:9,16]",
"INFO: pass 1: last_count: 36, count: 18",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:48,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:48,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:51,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:53,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]",
]
}
non_hoisted_function_after_return_2b: {
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,
hoist_funs: false, dead_code: true, conditionals: true, comparisons: true,
evaluate: true, booleans: true, loops: true, unused: true, keep_fargs: true,
if_return: true, join_vars: true, cascade: true, side_effects: true,
collapse_vars: false
}
input: {
function foo(x) {
@@ -138,173 +108,11 @@ non_hoisted_function_after_return_2b: {
}
}
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:6,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:6,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:8,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:8,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:12,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]",
// duplicate warnings no longer emitted
"WARN: Dropping unreachable code [test/compress/issue-1034.js:95,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:95,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]",
]
}

View File

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

View File

@@ -1,91 +1,90 @@
multiple_functions: {
options = {
hoist_funs: false,
if_return: true,
}
options = { if_return: true, hoist_funs: false };
input: {
( function() {
if ( !window ) {
return;
}
function f() {}
function g() {}
} )();
}
expect: {
( function() {
function f() {}
function g() {}
// NOTE: other compression steps will reduce this
// down to just `window`.
if ( window );
function f() {}
function g() {}
} )();
}
}
single_function: {
options = {
hoist_funs: false,
if_return: true,
}
options = { if_return: true, hoist_funs: false };
input: {
( function() {
if ( !window ) {
return;
}
function f() {}
} )();
}
expect: {
( function() {
if ( window );
function f() {}
if ( window );
} )();
}
}
deeply_nested: {
options = {
hoist_funs: false,
if_return: true,
}
options = { if_return: true, hoist_funs: false };
input: {
( function() {
if ( !window ) {
return;
}
function f() {}
function g() {}
if ( !document ) {
return;
}
function h() {}
} )();
}
expect: {
( function() {
function f() {}
function g() {}
function h() {}
// NOTE: other compression steps will reduce this
// down to just `window`.
if ( window )
if (document);
function f() {}
function g() {}
function h() {}
} )();
}
}
not_hoisted_when_already_nested: {
options = {
hoist_funs: false,
if_return: true,
}
options = { if_return: true, hoist_funs: false };
input: {
( function() {
if ( !window ) {
return;
}
if ( foo ) function f() {}
} )();
}
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: {
options = {
unused: true,
unused: true
}
input: {
var o = 42;
@@ -18,7 +18,7 @@ with_in_global_scope: {
}
with_in_function_scope: {
options = {
unused: true,
unused: true
}
input: {
function foo() {
@@ -40,7 +40,7 @@ with_in_function_scope: {
}
compress_with_with_in_other_scope: {
options = {
unused: true,
unused: true
}
input: {
function foo() {
@@ -69,7 +69,7 @@ compress_with_with_in_other_scope: {
}
with_using_existing_variable_outside_scope: {
options = {
unused: true,
unused: true
}
input: {
function f() {
@@ -99,7 +99,7 @@ with_using_existing_variable_outside_scope: {
}
check_drop_unused_in_peer_function: {
options = {
unused: true,
unused: true
}
input: {
function outer() {
@@ -148,7 +148,7 @@ check_drop_unused_in_peer_function: {
Infinity_not_in_with_scope: {
options = {
unused: true,
unused: true
}
input: {
var o = { Infinity: 'oInfinity' };
@@ -164,7 +164,7 @@ Infinity_not_in_with_scope: {
Infinity_in_with_scope: {
options = {
unused: true,
unused: true
}
input: {
var o = { Infinity: 'oInfinity' };
@@ -180,19 +180,20 @@ Infinity_in_with_scope: {
assorted_Infinity_NaN_undefined_in_with_scope: {
options = {
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
unused: true,
evaluate: true,
dead_code: true,
conditionals: true,
comparisons: true,
booleans: true,
hoist_funs: true,
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
sequences: false,
keep_infinity: false,
sequences: false,
side_effects: true,
unused: true,
}
input: {
var f = console.log;
@@ -242,19 +243,20 @@ assorted_Infinity_NaN_undefined_in_with_scope: {
assorted_Infinity_NaN_undefined_in_with_scope_keep_infinity: {
options = {
booleans: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
unused: true,
evaluate: true,
dead_code: true,
conditionals: true,
comparisons: true,
booleans: true,
hoist_funs: true,
keep_fargs: true,
if_return: true,
join_vars: true,
cascade: true,
side_effects: true,
sequences: false,
keep_infinity: true,
sequences: false,
side_effects: true,
unused: true,
}
input: {
var f = console.log;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,9 +1,9 @@
screw_ie8: {
options = {
ie8: false,
screw_ie8: true,
}
mangle = {
ie8: false,
screw_ie8: true,
}
input: {
try { throw "foo"; } catch (x) { console.log(x); }
@@ -16,10 +16,10 @@ screw_ie8: {
support_ie8: {
options = {
ie8: true,
screw_ie8: false,
}
mangle = {
ie8: true,
screw_ie8: false,
}
input: {
try { throw "foo"; } catch (x) { console.log(x); }
@@ -61,7 +61,7 @@ unsafe_undefined: {
options = {
conditionals: true,
if_return: true,
unsafe_undefined: true,
unsafe: true,
}
mangle = {}
input: {
@@ -85,3 +85,15 @@ unsafe_undefined: {
}
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 = {
collapse_vars: true,
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -19,7 +18,9 @@ chained_evaluation_1: {
expect: {
(function() {
(function() {
f(1).bar = 1;
var c;
c = f(1);
c.bar = 1;
})();
})();
}
@@ -29,7 +30,6 @@ chained_evaluation_2: {
options = {
collapse_vars: true,
evaluate: true,
reduce_funcs: true,
reduce_vars: true,
unused: true,
}
@@ -46,36 +46,10 @@ chained_evaluation_2: {
expect: {
(function() {
(function() {
var 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;
var c, b = "long piece of string";
c = f(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: {
options = {
booleans: true,
collapse_vars: true,
cascade: true,
conditionals: true,
evaluate: true,
join_vars: true,
@@ -11,6 +12,7 @@ issue_1639_1: {
}
input: {
var a = 100, b = 10;
var L1 = 5;
while (--L1 > 0) {
if ((--b), false) {
@@ -19,21 +21,21 @@ issue_1639_1: {
}
}
}
console.log(a, b);
}
expect: {
for (var a = 100, b = 10, L1 = 5, ignore; --L1 > 0;) {
--b;
}
for (var a = 100, b = 10, L1 = 5; --L1 > 0;)
if (--b, !1) var ignore = 0;
console.log(a, b);
}
expect_stdout: "100 6"
expect_stdout: true
}
issue_1639_2: {
options = {
booleans: true,
collapse_vars: true,
cascade: true,
conditionals: true,
evaluate: true,
join_vars: true,
@@ -42,12 +44,14 @@ issue_1639_2: {
}
input: {
var a = 100, b = 10;
function f19() {
if (++a, false)
if (a)
if (++a);
}
f19();
console.log(a, b);
}
expect: {
@@ -58,13 +62,13 @@ issue_1639_2: {
f19(),
console.log(a, b);
}
expect_stdout: "101 10"
expect_stdout: true
}
issue_1639_3: {
options = {
booleans: true,
collapse_vars: true,
cascade: true,
conditionals: true,
evaluate: true,
sequences: true,
@@ -80,5 +84,5 @@ issue_1639_3: {
a++,
console.log(a, b);
}
expect_stdout: "101 10"
expect_stdout: true
}

View File

@@ -1,6 +1,7 @@
f7: {
options = {
booleans: true,
cascade: true,
collapse_vars: true,
comparisons: true,
conditionals: true,
@@ -14,7 +15,6 @@ f7: {
negate_iife: true,
passes: 3,
properties: true,
reduce_funcs: true,
reduce_vars: true,
sequences: true,
side_effects: true,
@@ -35,7 +35,11 @@ f7: {
console.log(a, b);
}
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: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -35,7 +34,6 @@ side_effects_catch: {
side_effects_else: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -64,7 +62,6 @@ side_effects_else: {
side_effects_finally: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -101,7 +98,6 @@ side_effects_finally: {
side_effects_label: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
@@ -134,7 +130,6 @@ side_effects_label: {
side_effects_switch: {
options = {
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,

View File

@@ -1,10 +1,10 @@
mangle_catch: {
options = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
input: {
@@ -22,11 +22,11 @@ mangle_catch: {
mangle_catch_ie8: {
options = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
input: {
@@ -44,11 +44,11 @@ mangle_catch_ie8: {
mangle_catch_var: {
options = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
input: {
@@ -66,11 +66,11 @@ mangle_catch_var: {
mangle_catch_var_ie8: {
options = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
input: {
@@ -88,11 +88,11 @@ mangle_catch_var_ie8: {
mangle_catch_toplevel: {
options = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
input: {
@@ -104,17 +104,17 @@ mangle_catch_toplevel: {
}
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"
}
mangle_catch_ie8_toplevel: {
options = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
input: {
@@ -132,11 +132,11 @@ mangle_catch_ie8_toplevel: {
mangle_catch_var_toplevel: {
options = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
input: {
@@ -148,17 +148,17 @@ mangle_catch_var_toplevel: {
}
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"
}
mangle_catch_var_ie8_toplevel: {
options = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
input: {
@@ -176,11 +176,11 @@ mangle_catch_var_ie8_toplevel: {
mangle_catch_redef_1: {
options = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
input: {
@@ -198,11 +198,11 @@ mangle_catch_redef_1: {
mangle_catch_redef_1_ie8: {
options = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
input: {
@@ -220,11 +220,11 @@ mangle_catch_redef_1_ie8: {
mangle_catch_redef_1_toplevel: {
options = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
input: {
@@ -242,11 +242,11 @@ mangle_catch_redef_1_toplevel: {
mangle_catch_redef_1_ie8_toplevel: {
options = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
input: {
@@ -264,11 +264,11 @@ mangle_catch_redef_1_ie8_toplevel: {
mangle_catch_redef_2: {
options = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: false,
}
input: {
@@ -285,11 +285,11 @@ mangle_catch_redef_2: {
mangle_catch_redef_2_ie8: {
options = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: false,
}
input: {
@@ -306,11 +306,11 @@ mangle_catch_redef_2_ie8: {
mangle_catch_redef_2_toplevel: {
options = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
mangle = {
ie8: false,
screw_ie8: true,
toplevel: true,
}
input: {
@@ -327,11 +327,11 @@ mangle_catch_redef_2_toplevel: {
mangle_catch_redef_2_ie8_toplevel: {
options = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
mangle = {
ie8: true,
screw_ie8: false,
toplevel: true,
}
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_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: {
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: {
function f(n) {
@@ -19,58 +40,37 @@ function_iife_catch: {
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: {
mangle = {
ie8: false,
}
input: {
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_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_stdout: [
"3",
"undefined",
]
}
function_catch_catch_ie8: {
mangle = {
ie8: true,
screw_ie8: true,
}
input: {
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_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: [
"3",
"undefined",
]
}
function_catch_catch_ie8: {
mangle = {
screw_ie8: false,
}
input: {
var o = 0;

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,6 @@
iife_for: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -27,7 +26,6 @@ iife_for: {
iife_for_in: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -53,7 +51,6 @@ iife_for_in: {
iife_do: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -83,7 +80,6 @@ iife_do: {
iife_while: {
options = {
negate_iife: true,
reduce_funcs: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -125,8 +121,8 @@ label_do: {
label_while: {
options = {
dead_code: true,
evaluate: true,
dead_code: true,
loops: true,
}
input: {
@@ -134,5 +130,5 @@ label_while: {
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: {
options = {
global_defs: {
DEBUG: 0,
},
global_defs: { DEBUG: 0 }
}
input: {
DEBUG++;
@@ -18,9 +16,7 @@ do_not_update_lhs: {
do_update_rhs: {
options = {
global_defs: {
DEBUG: 0,
},
global_defs: { DEBUG: 0 }
}
input: {
MY_DEBUG = DEBUG;
@@ -39,10 +35,10 @@ mixed: {
DEBUG: 0,
ENV: 1,
FOO: 2,
},
}
}
input: {
var ENV = 3;
const ENV = 3;
var FOO = 4;
f(ENV * 10);
--FOO;
@@ -53,7 +49,7 @@ mixed: {
x = DEBUG;
}
expect: {
var ENV = 3;
const ENV = 3;
var FOO = 4;
f(10);
--FOO;
@@ -64,11 +60,11 @@ mixed: {
x = 0;
}
expect_warnings: [
"WARN: global_defs ENV redefined [test/compress/issue-208.js:1,12]",
"WARN: global_defs FOO redefined [test/compress/issue-208.js:2,12]",
"WARN: global_defs FOO redefined [test/compress/issue-208.js:4,10]",
"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:5,8]",
"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:6,8]",
"WARN: global_defs DEBUG redefined [test/compress/issue-208.js:7,8]",
'WARN: global_defs ENV redefined [test/compress/issue-208.js:41,14]',
'WARN: global_defs FOO redefined [test/compress/issue-208.js:42,12]',
'WARN: global_defs FOO redefined [test/compress/issue-208.js:44,10]',
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:45,8]',
'WARN: global_defs DEBUG redefined [test/compress/issue-208.js:46,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: {
options = {
conditionals: true,
}
options = { conditionals: true };
input: {
function foo(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: {
options = {
comparisons: true,
}
options = { comparisons: true };
input: {
x = a % b / b * c * 2;
x = a % b * 2

View File

@@ -1,111 +1,66 @@
issue_269_1: {
options = {
unsafe: true,
}
input: {
var x = {};
console.log(
String(x),
Number(x),
Boolean(x),
options = {unsafe: true};
input: {
f(
String(x),
Number(x),
Boolean(x),
String(),
Number(),
Boolean()
);
}
expect: {
var x = {};
console.log(
x + "", +x, !!x,
"", 0, false
);
}
expect_stdout: true
String(),
Number(),
Boolean()
);
}
expect: {
f(
x + '', +x, !!x,
'', 0, false
);
}
}
issue_269_dangers: {
options = {
unsafe: true,
}
input: {
var x = {};
console.log(
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
options = {unsafe: true};
input: {
f(
String(x, x),
Number(x, x),
Boolean(x, x)
);
}
expect: {
f(String(x, x), Number(x, x), Boolean(x, x));
}
}
issue_269_in_scope: {
options = {
unsafe: true,
}
input: {
var String, Number, Boolean;
var x = {};
console.log(
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
options = {unsafe: true};
input: {
var String, Number, Boolean;
f(
String(x),
Number(x, x),
Boolean(x)
);
}
expect: {
var String, Number, Boolean;
f(String(x), Number(x, x), Boolean(x));
}
}
strings_concat: {
options = {
strings: true,
unsafe: true,
}
input: {
var x = {};
console.log(
String(x + "str"),
String("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]',
]
options = {unsafe: true};
input: {
f(
String(x + 'str'),
String('str' + x)
);
}
expect: {
f(
x + 'str',
'str' + x
);
}
}

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: {
options = {
collapse_vars: true,
cascade: true,
sequences: true,
side_effects: true,
unused: true,
@@ -41,7 +41,7 @@ collapse: {
return void 0 !== ('function' === typeof b ? b() : b) && c();
}
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) {
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: {
options = {
unused: true,
}
options = { unused: true };
input: {
function a(b) {
for (var i = 0, e = b.qoo(); ; i++) {}
@@ -16,9 +14,7 @@ issue_44_valid_ast_1: {
}
issue_44_valid_ast_2: {
options = {
unused: true,
}
options = { unused: true };
input: {
function a(b) {
if (foo) for (var i = 0, e = b.qoo(); ; i++) {}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,7 @@
negate_booleans_1: {
options = {
comparisons: true,
}
comparisons: true
};
input: {
var a = !a || !b || !c || !d || !e || !f;
}
@@ -12,8 +12,8 @@ negate_booleans_1: {
negate_booleans_2: {
options = {
comparisons: true,
}
comparisons: true
};
input: {
var match = !x && // should not touch this one
(!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: {
options = {
side_effects: true,
}
options = { side_effects: true };
input: {
"use strict";
(0, 1, eval)();
(0, 1, logThis)();
(0, 1, _decorators.logThis)();
}
expect: {
"use strict";
(0, eval)();
logThis();
(0, _decorators.logThis)();
@@ -33,17 +13,13 @@ remove_redundant_sequence_items: {
}
dont_remove_this_binding_sequence: {
options = {
side_effects: true,
}
options = { side_effects: true };
input: {
"use strict";
(0, eval)();
(0, logThis)();
(0, _decorators.logThis)();
}
expect: {
"use strict";
(0, eval)();
logThis();
(0, _decorators.logThis)();

View File

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

View File

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

View File

@@ -1,11 +1,9 @@
this_binding_conditionals: {
options = {
conditionals: true,
evaluate: true,
side_effects: true,
}
evaluate : true
};
input: {
"use strict";
(1 && a)();
(0 || a)();
(0 || 1 && a)();
@@ -27,7 +25,6 @@ this_binding_conditionals: {
(1 ? eval : 0)();
}
expect: {
"use strict";
a();
a();
a();
@@ -53,111 +50,48 @@ this_binding_conditionals: {
this_binding_collapse_vars: {
options = {
collapse_vars: true,
unused: true,
}
toplevel: true,
};
input: {
function f() {
"use strict";
var c = a; c();
var d = a.b; d();
var e = eval; e();
}
var c = a; c();
var d = a.b; d();
var e = eval; e();
}
expect: {
function f() {
"use strict";
a();
(0, a.b)();
(0, eval)();
}
a();
(0, a.b)();
(0, eval)();
}
}
this_binding_side_effects: {
options = {
side_effects: true,
}
side_effects : true
};
input: {
(function(foo) {
(function (foo) {
(0, foo)();
(0, foo.bar)();
(0, eval)("console.log(foo);");
(0, eval)('console.log(foo);');
}());
(function(foo) {
"use strict";
(0, foo)();
(0, foo.bar)();
(0, eval)("console.log(foo);");
}());
(function(foo) {
(function (foo) {
var eval = console;
(0, foo)();
(0, foo.bar)();
(0, eval)("console.log(foo);");
(0, eval)('console.log(foo);');
}());
}
expect: {
(function(foo) {
(function (foo) {
foo();
(0, foo.bar)();
(0, eval)("console.log(foo);");
(0, eval)('console.log(foo);');
}());
(function(foo) {
"use strict";
foo();
(0, foo.bar)();
(0, eval)("console.log(foo);");
}());
(function(foo) {
(function (foo) {
var eval = console;
foo();
(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: {
options = {
booleans: true,
collapse_vars: true,
comparisons: true,
conditionals: true,
dead_code: true,
evaluate: true,
hoist_funs: true,
if_return: true,
join_vars: true,
keep_fargs: true,
loops: true,
properties: true,
sequences: false,
side_effects: true,
unused: true,
}
collapse_vars:true, sequences:false, properties:true, dead_code:true, conditionals:true,
comparisons:true, evaluate:true, booleans:true, loops:true, unused:true, hoist_funs:true,
keep_fargs:true, if_return:true, join_vars:true, cascade:true, side_effects:true
};
input: {
function f1() {
var e = 7;
@@ -58,10 +46,7 @@ eval_collapse_vars: {
}
eval_unused: {
options = {
keep_fargs: false,
unused: true,
}
options = { unused: true, keep_fargs: false };
input: {
function f1(a, eval, c, d, e) {
return a('c') + eval;

View File

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

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