Compare commits
69 Commits
harmony-v3
...
harmony-v3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e595171b9 | ||
|
|
6973abbfe1 | ||
|
|
4eb4cb656c | ||
|
|
193612ac67 | ||
|
|
95cfce68ea | ||
|
|
e0461dc3c8 | ||
|
|
ec4202590d | ||
|
|
5e2cd07d6f | ||
|
|
bea9dbd812 | ||
|
|
bc01a85ba0 | ||
|
|
c7c7960b5f | ||
|
|
fc98d212db | ||
|
|
13accdd745 | ||
|
|
287ec730f7 | ||
|
|
06166df999 | ||
|
|
e2dc9cf091 | ||
|
|
069df27bf1 | ||
|
|
3e7873217c | ||
|
|
e21bab7ce6 | ||
|
|
ac9a168fba | ||
|
|
81b64549ce | ||
|
|
082e004b87 | ||
|
|
983e69128b | ||
|
|
b335912e86 | ||
|
|
cc07f3b806 | ||
|
|
07e4b64f3a | ||
|
|
d3ce2bc9e7 | ||
|
|
cff3bf4914 | ||
|
|
4f57d8746b | ||
|
|
79cfac77bd | ||
|
|
224c14d49d | ||
|
|
7857354d85 | ||
|
|
b4aef753e7 | ||
|
|
424173d311 | ||
|
|
ec7cd1dcf7 | ||
|
|
7def684730 | ||
|
|
10f961c27b | ||
|
|
b483678ca7 | ||
|
|
cbbe6fad60 | ||
|
|
f96929c031 | ||
|
|
2b6657e967 | ||
|
|
1b2e6b81a2 | ||
|
|
f9e9898dc1 | ||
|
|
7c0c92943f | ||
|
|
62a66dfff4 | ||
|
|
c44d78db55 | ||
|
|
8c763bf2b5 | ||
|
|
2cab348341 | ||
|
|
aa1786dedf | ||
|
|
0d5df271a1 | ||
|
|
b56e1f178f | ||
|
|
9acace2cb6 | ||
|
|
0f2be1456c | ||
|
|
460218a3f8 | ||
|
|
e49416e4aa | ||
|
|
d4d7d99b70 | ||
|
|
6a696d0a7b | ||
|
|
1c9e13f47d | ||
|
|
b757450cd8 | ||
|
|
23ec484806 | ||
|
|
f1e1bb419a | ||
|
|
6a0af85c8b | ||
|
|
1eb15f46f1 | ||
|
|
09269be974 | ||
|
|
137cb73d1f | ||
|
|
bf832cde16 | ||
|
|
2972d58dbb | ||
|
|
2e22d38a02 | ||
|
|
ce27bcd69a |
11
README.md
11
README.md
@@ -67,7 +67,7 @@ a double dash to prevent input files being used as option arguments:
|
|||||||
`debug` Add debug prefix and suffix.
|
`debug` Add debug prefix and suffix.
|
||||||
`domprops` Mangle property names that overlaps
|
`domprops` Mangle property names that overlaps
|
||||||
with DOM properties.
|
with DOM properties.
|
||||||
`keep_quoted` Only mangle unquoted properies.
|
`keep_quoted` Only mangle unquoted properties.
|
||||||
`regex` Only mangle matched property names.
|
`regex` Only mangle matched property names.
|
||||||
`reserved` List of names that should not be mangled.
|
`reserved` List of names that should not be mangled.
|
||||||
-b, --beautify [options] Beautify output/specify output options:
|
-b, --beautify [options] Beautify output/specify output options:
|
||||||
@@ -782,7 +782,7 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
comparison are switching. Compression only works if both `comparisons` and
|
comparison are switching. Compression only works if both `comparisons` and
|
||||||
`unsafe_comps` are both set to true.
|
`unsafe_comps` are both set to true.
|
||||||
|
|
||||||
- `unsafe_Func` (default: `false`) -- compress and mangle `Function(args, code)`
|
- `unsafe_Function` (default: `false`) -- compress and mangle `Function(args, code)`
|
||||||
when both `args` and `code` are string literals.
|
when both `args` and `code` are string literals.
|
||||||
|
|
||||||
- `unsafe_math` (default: `false`) -- optimize numerical expressions like
|
- `unsafe_math` (default: `false`) -- optimize numerical expressions like
|
||||||
@@ -801,6 +801,10 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
|||||||
- `unsafe_regexp` (default: `false`) -- enable substitutions of variables with
|
- `unsafe_regexp` (default: `false`) -- enable substitutions of variables with
|
||||||
`RegExp` values the same way as if they are constants.
|
`RegExp` values the same way as if they are constants.
|
||||||
|
|
||||||
|
- `unsafe_undefined` (default: `false`) -- substitute `void 0` if there is a
|
||||||
|
variable named `undefined` in scope (variable name will be mangled, typically
|
||||||
|
reduced to a single character)
|
||||||
|
|
||||||
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple
|
- `unused` (default: `true`) -- drop unreferenced functions and variables (simple
|
||||||
direct variable assignments do not count as references unless set to `"keep_assign"`)
|
direct variable assignments do not count as references unless set to `"keep_assign"`)
|
||||||
|
|
||||||
@@ -993,9 +997,6 @@ when this flag is on:
|
|||||||
- `new Object()` → `{}`
|
- `new Object()` → `{}`
|
||||||
- `String(exp)` or `exp.toString()` → `"" + exp`
|
- `String(exp)` or `exp.toString()` → `"" + exp`
|
||||||
- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
|
- `new Object/RegExp/Function/Error/Array (...)` → we discard the `new`
|
||||||
- `void 0` → `undefined` (if there is a variable named "undefined" in
|
|
||||||
scope; we do it because the variable name will be mangled, typically
|
|
||||||
reduced to a single character)
|
|
||||||
|
|
||||||
### Conditional compilation
|
### Conditional compilation
|
||||||
|
|
||||||
|
|||||||
34
bin/uglifyjs
34
bin/uglifyjs
@@ -11,7 +11,7 @@ var path = require("path");
|
|||||||
var program = require("commander");
|
var program = require("commander");
|
||||||
var UglifyJS = require("../tools/node");
|
var UglifyJS = require("../tools/node");
|
||||||
|
|
||||||
var skip_keys = [ "cname", "enclosed", "inlined", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ];
|
var skip_keys = [ "cname", "inlined", "parent_scope", "scope", "uses_eval", "uses_with" ];
|
||||||
var files = {};
|
var files = {};
|
||||||
var options = {
|
var options = {
|
||||||
compress: false,
|
compress: false,
|
||||||
@@ -45,6 +45,7 @@ program.option("--ie8", "Support non-standard Internet Explorer 8.");
|
|||||||
program.option("--keep-classnames", "Do not mangle/drop class names.");
|
program.option("--keep-classnames", "Do not mangle/drop class names.");
|
||||||
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
|
program.option("--keep-fnames", "Do not mangle/drop function names. Useful for code relying on Function.prototype.name.");
|
||||||
program.option("--name-cache <file>", "File to hold mangled name mappings.");
|
program.option("--name-cache <file>", "File to hold mangled name mappings.");
|
||||||
|
program.option("--rename", "Force symbol expansion.");
|
||||||
program.option("--no-rename", "Disable symbol expansion.");
|
program.option("--no-rename", "Disable symbol expansion.");
|
||||||
program.option("--safari10", "Support non-standard Safari 10.");
|
program.option("--safari10", "Support non-standard Safari 10.");
|
||||||
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
|
program.option("--self", "Build UglifyJS as a library (implies --wrap UglifyJS)");
|
||||||
@@ -65,14 +66,12 @@ if (!program.output && program.sourceMap && program.sourceMap.url != "inline") {
|
|||||||
"compress",
|
"compress",
|
||||||
"ie8",
|
"ie8",
|
||||||
"mangle",
|
"mangle",
|
||||||
"rename",
|
|
||||||
"safari10",
|
"safari10",
|
||||||
"sourceMap",
|
"sourceMap",
|
||||||
"toplevel",
|
"toplevel",
|
||||||
"wrap"
|
"wrap"
|
||||||
].forEach(function(name) {
|
].forEach(function(name) {
|
||||||
if (name in program) {
|
if (name in program) {
|
||||||
if (name == "rename" && program[name]) return;
|
|
||||||
options[name] = program[name];
|
options[name] = program[name];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -132,6 +131,11 @@ if (program.parse) {
|
|||||||
fatal("ERROR: inline source map only works with built-in parser");
|
fatal("ERROR: inline source map only works with built-in parser");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (~program.rawArgs.indexOf("--rename")) {
|
||||||
|
options.rename = true;
|
||||||
|
} else if (!program.rename) {
|
||||||
|
options.rename = false;
|
||||||
|
}
|
||||||
var convert_path = function(name) {
|
var convert_path = function(name) {
|
||||||
return name;
|
return name;
|
||||||
};
|
};
|
||||||
@@ -234,7 +238,20 @@ function run() {
|
|||||||
}
|
}
|
||||||
fatal(ex);
|
fatal(ex);
|
||||||
} else if (program.output == "ast") {
|
} else if (program.output == "ast") {
|
||||||
|
if (!options.compress && !options.mangle) {
|
||||||
|
result.ast.figure_out_scope({});
|
||||||
|
}
|
||||||
print(JSON.stringify(result.ast, function(key, value) {
|
print(JSON.stringify(result.ast, function(key, value) {
|
||||||
|
if (value) switch (key) {
|
||||||
|
case "thedef":
|
||||||
|
return symdef(value);
|
||||||
|
case "enclosed":
|
||||||
|
return value.length ? value.map(symdef) : undefined;
|
||||||
|
case "variables":
|
||||||
|
case "functions":
|
||||||
|
case "globals":
|
||||||
|
return value.size() ? value.map(symdef) : undefined;
|
||||||
|
}
|
||||||
if (skip_key(key)) return;
|
if (skip_key(key)) return;
|
||||||
if (value instanceof UglifyJS.AST_Token) return;
|
if (value instanceof UglifyJS.AST_Token) return;
|
||||||
if (value instanceof UglifyJS.Dictionary) return;
|
if (value instanceof UglifyJS.Dictionary) return;
|
||||||
@@ -242,6 +259,11 @@ function run() {
|
|||||||
var result = {
|
var result = {
|
||||||
_class: "AST_" + value.TYPE
|
_class: "AST_" + value.TYPE
|
||||||
};
|
};
|
||||||
|
if (value.block_scope) {
|
||||||
|
result.variables = value.block_scope.variables;
|
||||||
|
result.functions = value.block_scope.functions;
|
||||||
|
result.enclosed = value.block_scope.enclosed;
|
||||||
|
}
|
||||||
value.CTOR.PROPS.forEach(function(prop) {
|
value.CTOR.PROPS.forEach(function(prop) {
|
||||||
result[prop] = value[prop];
|
result[prop] = value[prop];
|
||||||
});
|
});
|
||||||
@@ -388,6 +410,12 @@ function skip_key(key) {
|
|||||||
return skip_keys.indexOf(key) >= 0;
|
return skip_keys.indexOf(key) >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function symdef(def) {
|
||||||
|
var ret = (1e6 + def.id) + " " + def.name;
|
||||||
|
if (def.mangled_name) ret += " " + def.mangled_name;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
function format_object(obj) {
|
function format_object(obj) {
|
||||||
var lines = [];
|
var lines = [];
|
||||||
var padding = "";
|
var padding = "";
|
||||||
|
|||||||
14
lib/ast.js
14
lib/ast.js
@@ -267,11 +267,10 @@ var AST_For = DEFNODE("For", "init condition step", {
|
|||||||
}
|
}
|
||||||
}, AST_IterationStatement);
|
}, AST_IterationStatement);
|
||||||
|
|
||||||
var AST_ForIn = DEFNODE("ForIn", "init name object", {
|
var AST_ForIn = DEFNODE("ForIn", "init object", {
|
||||||
$documentation: "A `for ... in` statement",
|
$documentation: "A `for ... in` statement",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
init: "[AST_Node] the `for/in` initialization code",
|
init: "[AST_Node] the `for/in` initialization code",
|
||||||
name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
|
|
||||||
object: "[AST_Node] the object that we're looping through"
|
object: "[AST_Node] the object that we're looping through"
|
||||||
},
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
@@ -319,6 +318,13 @@ var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent
|
|||||||
self = self.parent_scope;
|
self = self.parent_scope;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
},
|
||||||
|
clone: function(deep) {
|
||||||
|
var node = this._clone(deep);
|
||||||
|
if (this.variables) node.variables = this.variables.clone();
|
||||||
|
if (this.functions) node.functions = this.functions.clone();
|
||||||
|
if (this.enclosed) node.enclosed = this.enclosed.slice();
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
}, AST_Block);
|
}, AST_Block);
|
||||||
|
|
||||||
@@ -863,8 +869,8 @@ var AST_Object = DEFNODE("Object", "properties", {
|
|||||||
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
|
var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
|
||||||
$documentation: "Base class for literal object properties",
|
$documentation: "Base class for literal object properties",
|
||||||
$propdoc: {
|
$propdoc: {
|
||||||
key: "[string|AST_Node] the property name converted to a string for ObjectKeyVal. For setters, getters and computed property this is an arbitrary AST_Node",
|
key: "[string|AST_Node] property name. For ObjectKeyVal this is a string. For getters, setters and computed property this is an AST_Node.",
|
||||||
value: "[AST_Node] property value. For setters and getters this is an AST_Accessor."
|
value: "[AST_Node] property value. For getters and setters this is an AST_Accessor."
|
||||||
},
|
},
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
|
|||||||
579
lib/compress.js
579
lib/compress.js
@@ -89,11 +89,12 @@ function Compressor(options, false_by_default) {
|
|||||||
unsafe : false,
|
unsafe : false,
|
||||||
unsafe_arrows : false,
|
unsafe_arrows : false,
|
||||||
unsafe_comps : false,
|
unsafe_comps : false,
|
||||||
unsafe_Func : false,
|
unsafe_Function: false,
|
||||||
unsafe_math : false,
|
unsafe_math : false,
|
||||||
unsafe_methods: false,
|
unsafe_methods: false,
|
||||||
unsafe_proto : false,
|
unsafe_proto : false,
|
||||||
unsafe_regexp : false,
|
unsafe_regexp : false,
|
||||||
|
unsafe_undefined: false,
|
||||||
unused : !false_by_default,
|
unused : !false_by_default,
|
||||||
warnings : false,
|
warnings : false,
|
||||||
}, true);
|
}, true);
|
||||||
@@ -178,7 +179,8 @@ merge(Compressor.prototype, {
|
|||||||
node.process_expression(true);
|
node.process_expression(true);
|
||||||
}
|
}
|
||||||
var passes = +this.options.passes || 1;
|
var passes = +this.options.passes || 1;
|
||||||
var last_count = 1 / 0;
|
var min_count = 1 / 0;
|
||||||
|
var stopping = false;
|
||||||
var mangle = { ie8: this.option("ie8") };
|
var mangle = { ie8: this.option("ie8") };
|
||||||
for (var pass = 0; pass < passes; pass++) {
|
for (var pass = 0; pass < passes; pass++) {
|
||||||
node.figure_out_scope(mangle);
|
node.figure_out_scope(mangle);
|
||||||
@@ -190,9 +192,15 @@ merge(Compressor.prototype, {
|
|||||||
node.walk(new TreeWalker(function() {
|
node.walk(new TreeWalker(function() {
|
||||||
count++;
|
count++;
|
||||||
}));
|
}));
|
||||||
this.info("pass " + pass + ": last_count: " + last_count + ", count: " + count);
|
this.info("pass " + pass + ": last_count: " + min_count + ", count: " + count);
|
||||||
if (count >= last_count) break;
|
if (count < min_count) {
|
||||||
last_count = count;
|
min_count = count;
|
||||||
|
stopping = false;
|
||||||
|
} else if (stopping) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
stopping = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.option("expression")) {
|
if (this.option("expression")) {
|
||||||
@@ -411,14 +419,15 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function read_property(obj, key) {
|
function read_property(obj, key) {
|
||||||
if (key instanceof AST_Constant) key = key.getValue();
|
key = get_value(key);
|
||||||
if (key instanceof AST_Node) return null;
|
if (key instanceof AST_Node) return;
|
||||||
var value;
|
var value;
|
||||||
if (obj instanceof AST_Array) {
|
if (obj instanceof AST_Array) {
|
||||||
var elements = obj.elements;
|
var elements = obj.elements;
|
||||||
if (key == "length") return make_node_from_constant(elements.length, obj);
|
if (key == "length") return make_node_from_constant(elements.length, obj);
|
||||||
if (typeof key == "number" && key in elements) value = elements[key];
|
if (typeof key == "number" && key in elements) value = elements[key];
|
||||||
} else if (obj instanceof AST_Object) {
|
} else if (obj instanceof AST_Object) {
|
||||||
|
key = "" + key;
|
||||||
var props = obj.properties;
|
var props = obj.properties;
|
||||||
for (var i = props.length; --i >= 0;) {
|
for (var i = props.length; --i >= 0;) {
|
||||||
var prop = props[i];
|
var prop = props[i];
|
||||||
@@ -489,8 +498,9 @@ merge(Compressor.prototype, {
|
|||||||
if (node instanceof AST_SymbolRef) d.references.push(node);
|
if (node instanceof AST_SymbolRef) d.references.push(node);
|
||||||
d.fixed = false;
|
d.fixed = false;
|
||||||
});
|
});
|
||||||
def(AST_Accessor, function(tw, descend) {
|
def(AST_Accessor, function(tw, descend, compressor) {
|
||||||
push(tw);
|
push(tw);
|
||||||
|
reset_variables(tw, compressor, this);
|
||||||
descend();
|
descend();
|
||||||
pop(tw);
|
pop(tw);
|
||||||
return true;
|
return true;
|
||||||
@@ -917,9 +927,8 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function loop_body(x) {
|
function loop_body(x) {
|
||||||
if (x instanceof AST_Switch) return x;
|
if (x instanceof AST_IterationStatement) {
|
||||||
if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
|
return x.body instanceof AST_BlockStatement ? x.body : x;
|
||||||
return (x.body instanceof AST_BlockStatement ? x.body : x);
|
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
};
|
};
|
||||||
@@ -947,6 +956,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function tighten_body(statements, compressor) {
|
function tighten_body(statements, compressor) {
|
||||||
|
var scope = compressor.find_parent(AST_Scope).get_defun_scope();
|
||||||
var CHANGED, max_iter = 10;
|
var CHANGED, max_iter = 10;
|
||||||
do {
|
do {
|
||||||
CHANGED = false;
|
CHANGED = false;
|
||||||
@@ -962,7 +972,7 @@ merge(Compressor.prototype, {
|
|||||||
sequencesize_2(statements, compressor);
|
sequencesize_2(statements, compressor);
|
||||||
}
|
}
|
||||||
if (compressor.option("join_vars")) {
|
if (compressor.option("join_vars")) {
|
||||||
join_consecutive_vars(statements, compressor);
|
join_consecutive_vars(statements);
|
||||||
}
|
}
|
||||||
if (compressor.option("collapse_vars")) {
|
if (compressor.option("collapse_vars")) {
|
||||||
collapse(statements, compressor);
|
collapse(statements, compressor);
|
||||||
@@ -978,7 +988,6 @@ merge(Compressor.prototype, {
|
|||||||
// Will not attempt to collapse assignments into or past code blocks
|
// Will not attempt to collapse assignments into or past code blocks
|
||||||
// which are not sequentially executed, e.g. loops and conditionals.
|
// which are not sequentially executed, e.g. loops and conditionals.
|
||||||
function collapse(statements, compressor) {
|
function collapse(statements, compressor) {
|
||||||
var scope = compressor.find_parent(AST_Scope).get_defun_scope();
|
|
||||||
if (scope.uses_eval || scope.uses_with) return statements;
|
if (scope.uses_eval || scope.uses_with) return statements;
|
||||||
var args;
|
var args;
|
||||||
var candidates = [];
|
var candidates = [];
|
||||||
@@ -1280,14 +1289,31 @@ merge(Compressor.prototype, {
|
|||||||
expr.definitions.forEach(extract_candidates);
|
expr.definitions.forEach(extract_candidates);
|
||||||
} else if (expr instanceof AST_DWLoop) {
|
} else if (expr instanceof AST_DWLoop) {
|
||||||
extract_candidates(expr.condition);
|
extract_candidates(expr.condition);
|
||||||
|
if (!(expr.body instanceof AST_Block)) {
|
||||||
|
extract_candidates(expr.body);
|
||||||
|
}
|
||||||
} else if (expr instanceof AST_Exit) {
|
} else if (expr instanceof AST_Exit) {
|
||||||
if (expr.value) extract_candidates(expr.value);
|
if (expr.value) extract_candidates(expr.value);
|
||||||
} else if (expr instanceof AST_For) {
|
} else if (expr instanceof AST_For) {
|
||||||
if (expr.init) extract_candidates(expr.init);
|
if (expr.init) extract_candidates(expr.init);
|
||||||
if (expr.condition) extract_candidates(expr.condition);
|
if (expr.condition) extract_candidates(expr.condition);
|
||||||
if (expr.step) extract_candidates(expr.step);
|
if (expr.step) extract_candidates(expr.step);
|
||||||
|
if (!(expr.body instanceof AST_Block)) {
|
||||||
|
extract_candidates(expr.body);
|
||||||
|
}
|
||||||
|
} else if (expr instanceof AST_ForIn) {
|
||||||
|
extract_candidates(expr.object);
|
||||||
|
if (!(expr.body instanceof AST_Block)) {
|
||||||
|
extract_candidates(expr.body);
|
||||||
|
}
|
||||||
} else if (expr instanceof AST_If) {
|
} else if (expr instanceof AST_If) {
|
||||||
extract_candidates(expr.condition);
|
extract_candidates(expr.condition);
|
||||||
|
if (!(expr.body instanceof AST_Block)) {
|
||||||
|
extract_candidates(expr.body);
|
||||||
|
}
|
||||||
|
if (expr.alternative && !(expr.alternative instanceof AST_Block)) {
|
||||||
|
extract_candidates(expr.alternative);
|
||||||
|
}
|
||||||
} else if (expr instanceof AST_Sequence) {
|
} else if (expr instanceof AST_Sequence) {
|
||||||
expr.expressions.forEach(extract_candidates);
|
expr.expressions.forEach(extract_candidates);
|
||||||
} else if (expr instanceof AST_SimpleStatement) {
|
} else if (expr instanceof AST_SimpleStatement) {
|
||||||
@@ -1314,10 +1340,12 @@ merge(Compressor.prototype, {
|
|||||||
if (parent instanceof AST_Call) return node;
|
if (parent instanceof AST_Call) return node;
|
||||||
if (parent instanceof AST_Case) return node;
|
if (parent instanceof AST_Case) return node;
|
||||||
if (parent instanceof AST_Conditional) return node;
|
if (parent instanceof AST_Conditional) return node;
|
||||||
|
if (parent instanceof AST_Definitions) return find_stop(parent, level + 1);
|
||||||
if (parent instanceof AST_Exit) return node;
|
if (parent instanceof AST_Exit) return node;
|
||||||
if (parent instanceof AST_If) return node;
|
if (parent instanceof AST_If) return node;
|
||||||
if (parent instanceof AST_IterationStatement) return node;
|
if (parent instanceof AST_IterationStatement) return node;
|
||||||
if (parent instanceof AST_Sequence) return find_stop(parent, level + 1);
|
if (parent instanceof AST_Sequence) return find_stop(parent, level + 1);
|
||||||
|
if (parent instanceof AST_SimpleStatement) return find_stop(parent, level + 1);
|
||||||
if (parent instanceof AST_Switch) return node;
|
if (parent instanceof AST_Switch) return node;
|
||||||
if (parent instanceof AST_VarDef) return node;
|
if (parent instanceof AST_VarDef) return node;
|
||||||
return null;
|
return null;
|
||||||
@@ -1640,7 +1668,7 @@ merge(Compressor.prototype, {
|
|||||||
function next_index(i) {
|
function next_index(i) {
|
||||||
for (var j = i + 1, len = statements.length; j < len; j++) {
|
for (var j = i + 1, len = statements.length; j < len; j++) {
|
||||||
var stat = statements[j];
|
var stat = statements[j];
|
||||||
if (!(stat instanceof AST_Definitions && declarations_only(stat))) {
|
if (!(stat instanceof AST_Var && declarations_only(stat))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1650,7 +1678,7 @@ merge(Compressor.prototype, {
|
|||||||
function prev_index(i) {
|
function prev_index(i) {
|
||||||
for (var j = i; --j >= 0;) {
|
for (var j = i; --j >= 0;) {
|
||||||
var stat = statements[j];
|
var stat = statements[j];
|
||||||
if (!(stat instanceof AST_Definitions && declarations_only(stat))) {
|
if (!(stat instanceof AST_Var && declarations_only(stat))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1731,7 +1759,7 @@ merge(Compressor.prototype, {
|
|||||||
var stat = null;
|
var stat = null;
|
||||||
for (var i = 0, len = block.body.length; i < len; i++) {
|
for (var i = 0, len = block.body.length; i < len; i++) {
|
||||||
var line = block.body[i];
|
var line = block.body[i];
|
||||||
if (line instanceof AST_Definitions && declarations_only(line)) {
|
if (line instanceof AST_Var && declarations_only(line)) {
|
||||||
decls.push(line);
|
decls.push(line);
|
||||||
} else if (stat) {
|
} else if (stat) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1753,37 +1781,36 @@ merge(Compressor.prototype, {
|
|||||||
for (var i = 0; i < statements.length; i++) {
|
for (var i = 0; i < statements.length; i++) {
|
||||||
var stat = statements[i];
|
var stat = statements[i];
|
||||||
if (prev) {
|
if (prev) {
|
||||||
if (stat instanceof AST_For && !(stat.init instanceof AST_Definitions)) {
|
if (stat instanceof AST_Exit) {
|
||||||
var abort = false;
|
stat.value = cons_seq(stat.value || make_node(AST_Undefined, stat).transform(compressor));
|
||||||
prev.body.walk(new TreeWalker(function(node) {
|
} else if (stat instanceof AST_For) {
|
||||||
if (abort || node instanceof AST_Scope) return true;
|
if (!(stat.init instanceof AST_Definitions)) {
|
||||||
if (node instanceof AST_Binary && node.operator == "in") {
|
var abort = false;
|
||||||
abort = true;
|
prev.body.walk(new TreeWalker(function(node) {
|
||||||
return true;
|
if (abort || node instanceof AST_Scope) return true;
|
||||||
}
|
if (node instanceof AST_Binary && node.operator == "in") {
|
||||||
}));
|
abort = true;
|
||||||
if (!abort) {
|
return true;
|
||||||
if (stat.init) stat.init = cons_seq(stat.init);
|
}
|
||||||
else {
|
}));
|
||||||
stat.init = prev.body;
|
if (!abort) {
|
||||||
n--;
|
if (stat.init) stat.init = cons_seq(stat.init);
|
||||||
CHANGED = true;
|
else {
|
||||||
|
stat.init = prev.body;
|
||||||
|
n--;
|
||||||
|
CHANGED = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (stat instanceof AST_ForIn) {
|
||||||
else if (stat instanceof AST_If) {
|
if (!(stat.init instanceof AST_Const) && !(stat.init instanceof AST_Let)) {
|
||||||
|
stat.object = cons_seq(stat.object);
|
||||||
|
}
|
||||||
|
} else if (stat instanceof AST_If) {
|
||||||
stat.condition = cons_seq(stat.condition);
|
stat.condition = cons_seq(stat.condition);
|
||||||
}
|
} else if (stat instanceof AST_Switch) {
|
||||||
else if (stat instanceof AST_With) {
|
|
||||||
stat.expression = cons_seq(stat.expression);
|
stat.expression = cons_seq(stat.expression);
|
||||||
}
|
} else if (stat instanceof AST_With) {
|
||||||
else if (stat instanceof AST_Exit && stat.value) {
|
|
||||||
stat.value = cons_seq(stat.value);
|
|
||||||
}
|
|
||||||
else if (stat instanceof AST_Exit) {
|
|
||||||
stat.value = cons_seq(make_node(AST_Undefined, stat).transform(compressor));
|
|
||||||
}
|
|
||||||
else if (stat instanceof AST_Switch) {
|
|
||||||
stat.expression = cons_seq(stat.expression);
|
stat.expression = cons_seq(stat.expression);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1813,7 +1840,49 @@ merge(Compressor.prototype, {
|
|||||||
statements.length = n;
|
statements.length = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
function join_consecutive_vars(statements, compressor) {
|
function join_object_assignments(defn, body) {
|
||||||
|
if (!(defn instanceof AST_Definitions)) return;
|
||||||
|
var def = defn.definitions[defn.definitions.length - 1];
|
||||||
|
if (!(def.value instanceof AST_Object)) return;
|
||||||
|
var exprs;
|
||||||
|
if (body instanceof AST_Assign) {
|
||||||
|
exprs = [ body ];
|
||||||
|
} else if (body instanceof AST_Sequence) {
|
||||||
|
exprs = body.expressions.slice();
|
||||||
|
}
|
||||||
|
if (!exprs) return;
|
||||||
|
var trimmed = false;
|
||||||
|
do {
|
||||||
|
var node = exprs[0];
|
||||||
|
if (!(node instanceof AST_Assign)) break;
|
||||||
|
if (node.operator != "=") break;
|
||||||
|
if (!(node.left instanceof AST_PropAccess)) break;
|
||||||
|
var sym = node.left.expression;
|
||||||
|
if (!(sym instanceof AST_SymbolRef)) break;
|
||||||
|
if (def.name.name != sym.name) break;
|
||||||
|
if (!node.right.is_constant_expression(scope)) break;
|
||||||
|
var prop = node.left.property;
|
||||||
|
if (prop instanceof AST_Node) {
|
||||||
|
prop = prop.evaluate(compressor);
|
||||||
|
}
|
||||||
|
if (prop instanceof AST_Node) break;
|
||||||
|
prop = "" + prop;
|
||||||
|
if (compressor.option("ecma") < 6 && compressor.has_directive("use strict")) {
|
||||||
|
if (!all(def.value.properties, function(node) {
|
||||||
|
return node.key != prop && node.key.name != prop;
|
||||||
|
})) break;
|
||||||
|
}
|
||||||
|
def.value.properties.push(make_node(AST_ObjectKeyVal, node, {
|
||||||
|
key: prop,
|
||||||
|
value: node.right
|
||||||
|
}));
|
||||||
|
exprs.shift();
|
||||||
|
trimmed = true;
|
||||||
|
} while (exprs.length);
|
||||||
|
return trimmed && exprs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function join_consecutive_vars(statements) {
|
||||||
var defs;
|
var defs;
|
||||||
for (var i = 0, j = -1, len = statements.length; i < len; i++) {
|
for (var i = 0, j = -1, len = statements.length; i < len; i++) {
|
||||||
var stat = statements[i];
|
var stat = statements[i];
|
||||||
@@ -1829,8 +1898,15 @@ merge(Compressor.prototype, {
|
|||||||
statements[++j] = stat;
|
statements[++j] = stat;
|
||||||
defs = stat;
|
defs = stat;
|
||||||
}
|
}
|
||||||
|
} else if (stat instanceof AST_Exit) {
|
||||||
|
stat.value = extract_object_assignments(stat.value);
|
||||||
} else if (stat instanceof AST_For) {
|
} else if (stat instanceof AST_For) {
|
||||||
if (prev instanceof AST_Var && (!stat.init || stat.init.TYPE == prev.TYPE)) {
|
var exprs = join_object_assignments(prev, stat.init);
|
||||||
|
if (exprs) {
|
||||||
|
CHANGED = true;
|
||||||
|
stat.init = exprs.length ? make_sequence(stat.init, exprs) : null;
|
||||||
|
statements[++j] = stat;
|
||||||
|
} else if (prev instanceof AST_Var && (!stat.init || stat.init.TYPE == prev.TYPE)) {
|
||||||
if (stat.init) {
|
if (stat.init) {
|
||||||
prev.definitions = prev.definitions.concat(stat.init.definitions);
|
prev.definitions = prev.definitions.concat(stat.init.definitions);
|
||||||
}
|
}
|
||||||
@@ -1845,11 +1921,43 @@ merge(Compressor.prototype, {
|
|||||||
} else {
|
} else {
|
||||||
statements[++j] = stat;
|
statements[++j] = stat;
|
||||||
}
|
}
|
||||||
|
} else if (stat instanceof AST_ForIn) {
|
||||||
|
stat.object = extract_object_assignments(stat.object);
|
||||||
|
} else if (stat instanceof AST_If) {
|
||||||
|
stat.condition = extract_object_assignments(stat.condition);
|
||||||
|
} else if (stat instanceof AST_SimpleStatement) {
|
||||||
|
var exprs = join_object_assignments(prev, stat.body);
|
||||||
|
if (exprs) {
|
||||||
|
CHANGED = true;
|
||||||
|
if (!exprs.length) continue;
|
||||||
|
stat.body = make_sequence(stat.body, exprs);
|
||||||
|
}
|
||||||
|
statements[++j] = stat;
|
||||||
|
} else if (stat instanceof AST_Switch) {
|
||||||
|
stat.expression = extract_object_assignments(stat.expression);
|
||||||
|
} else if (stat instanceof AST_With) {
|
||||||
|
stat.expression = extract_object_assignments(stat.expression);
|
||||||
} else {
|
} else {
|
||||||
statements[++j] = stat;
|
statements[++j] = stat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
statements.length = j + 1;
|
statements.length = j + 1;
|
||||||
|
|
||||||
|
function extract_object_assignments(value) {
|
||||||
|
statements[++j] = stat;
|
||||||
|
var exprs = join_object_assignments(prev, value);
|
||||||
|
if (exprs) {
|
||||||
|
CHANGED = true;
|
||||||
|
if (exprs.length) {
|
||||||
|
return make_sequence(value, exprs);
|
||||||
|
} else if (value instanceof AST_Sequence) {
|
||||||
|
return value.tail_node().left;
|
||||||
|
} else {
|
||||||
|
return value.left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1881,6 +1989,18 @@ merge(Compressor.prototype, {
|
|||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function get_value(key) {
|
||||||
|
if (key instanceof AST_Constant) {
|
||||||
|
return key.getValue();
|
||||||
|
}
|
||||||
|
if (key instanceof AST_UnaryPrefix
|
||||||
|
&& key.operator == "void"
|
||||||
|
&& key.expression instanceof AST_Constant) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
function is_undefined(node, compressor) {
|
function is_undefined(node, compressor) {
|
||||||
return node.is_undefined
|
return node.is_undefined
|
||||||
|| node instanceof AST_Undefined
|
|| node instanceof AST_Undefined
|
||||||
@@ -2129,6 +2249,95 @@ merge(Compressor.prototype, {
|
|||||||
return (first_in_statement(compressor) ? best_of_statement : best_of_expression)(ast1, ast2);
|
return (first_in_statement(compressor) ? best_of_statement : best_of_expression)(ast1, ast2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function convert_to_predicate(obj) {
|
||||||
|
for (var key in obj) {
|
||||||
|
obj[key] = makePredicate(obj[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var object_fns = [
|
||||||
|
"constructor",
|
||||||
|
"toString",
|
||||||
|
"valueOf",
|
||||||
|
];
|
||||||
|
var native_fns = {
|
||||||
|
Array: [
|
||||||
|
"indexOf",
|
||||||
|
"join",
|
||||||
|
"lastIndexOf",
|
||||||
|
"slice",
|
||||||
|
].concat(object_fns),
|
||||||
|
Boolean: object_fns,
|
||||||
|
Number: [
|
||||||
|
"toExponential",
|
||||||
|
"toFixed",
|
||||||
|
"toPrecision",
|
||||||
|
].concat(object_fns),
|
||||||
|
Object: object_fns,
|
||||||
|
RegExp: [
|
||||||
|
"test",
|
||||||
|
].concat(object_fns),
|
||||||
|
String: [
|
||||||
|
"charAt",
|
||||||
|
"charCodeAt",
|
||||||
|
"concat",
|
||||||
|
"indexOf",
|
||||||
|
"italics",
|
||||||
|
"lastIndexOf",
|
||||||
|
"match",
|
||||||
|
"replace",
|
||||||
|
"search",
|
||||||
|
"slice",
|
||||||
|
"split",
|
||||||
|
"substr",
|
||||||
|
"substring",
|
||||||
|
"trim",
|
||||||
|
].concat(object_fns),
|
||||||
|
};
|
||||||
|
convert_to_predicate(native_fns);
|
||||||
|
var static_fns = {
|
||||||
|
Array: [
|
||||||
|
"isArray",
|
||||||
|
],
|
||||||
|
Math: [
|
||||||
|
"abs",
|
||||||
|
"acos",
|
||||||
|
"asin",
|
||||||
|
"atan",
|
||||||
|
"ceil",
|
||||||
|
"cos",
|
||||||
|
"exp",
|
||||||
|
"floor",
|
||||||
|
"log",
|
||||||
|
"round",
|
||||||
|
"sin",
|
||||||
|
"sqrt",
|
||||||
|
"tan",
|
||||||
|
"atan2",
|
||||||
|
"pow",
|
||||||
|
"max",
|
||||||
|
"min",
|
||||||
|
],
|
||||||
|
Number: [
|
||||||
|
"isFinite",
|
||||||
|
"isNaN",
|
||||||
|
],
|
||||||
|
Object: [
|
||||||
|
"create",
|
||||||
|
"getOwnPropertyDescriptor",
|
||||||
|
"getOwnPropertyNames",
|
||||||
|
"getPrototypeOf",
|
||||||
|
"isExtensible",
|
||||||
|
"isFrozen",
|
||||||
|
"isSealed",
|
||||||
|
"keys",
|
||||||
|
],
|
||||||
|
String: [
|
||||||
|
"fromCharCode",
|
||||||
|
],
|
||||||
|
};
|
||||||
|
convert_to_predicate(static_fns);
|
||||||
|
|
||||||
// methods to evaluate a constant expression
|
// methods to evaluate a constant expression
|
||||||
(function(def){
|
(function(def){
|
||||||
// If the node has been successfully reduced to a constant,
|
// If the node has been successfully reduced to a constant,
|
||||||
@@ -2171,7 +2380,10 @@ merge(Compressor.prototype, {
|
|||||||
var elements = [];
|
var elements = [];
|
||||||
for (var i = 0, len = this.elements.length; i < len; i++) {
|
for (var i = 0, len = this.elements.length; i < len; i++) {
|
||||||
var element = this.elements[i];
|
var element = this.elements[i];
|
||||||
if (element instanceof AST_Function) continue;
|
if (element instanceof AST_Function) {
|
||||||
|
elements.push(element);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
var value = element._eval(compressor, depth);
|
var value = element._eval(compressor, depth);
|
||||||
if (element === value) return this;
|
if (element === value) return this;
|
||||||
elements.push(value);
|
elements.push(value);
|
||||||
@@ -2301,13 +2513,9 @@ merge(Compressor.prototype, {
|
|||||||
Array: Array,
|
Array: Array,
|
||||||
Math: Math,
|
Math: Math,
|
||||||
Number: Number,
|
Number: Number,
|
||||||
|
Object: Object,
|
||||||
String: String,
|
String: String,
|
||||||
};
|
};
|
||||||
function convert_to_predicate(obj) {
|
|
||||||
for (var key in obj) {
|
|
||||||
obj[key] = makePredicate(obj[key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var static_values = {
|
var static_values = {
|
||||||
Math: [
|
Math: [
|
||||||
"E",
|
"E",
|
||||||
@@ -2348,77 +2556,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
});
|
});
|
||||||
var object_fns = [
|
|
||||||
"constructor",
|
|
||||||
"toString",
|
|
||||||
"valueOf",
|
|
||||||
];
|
|
||||||
var native_fns = {
|
|
||||||
Array: [
|
|
||||||
"indexOf",
|
|
||||||
"join",
|
|
||||||
"lastIndexOf",
|
|
||||||
"slice",
|
|
||||||
].concat(object_fns),
|
|
||||||
Boolean: object_fns,
|
|
||||||
Number: [
|
|
||||||
"toExponential",
|
|
||||||
"toFixed",
|
|
||||||
"toPrecision",
|
|
||||||
].concat(object_fns),
|
|
||||||
RegExp: [
|
|
||||||
"test",
|
|
||||||
].concat(object_fns),
|
|
||||||
String: [
|
|
||||||
"charAt",
|
|
||||||
"charCodeAt",
|
|
||||||
"concat",
|
|
||||||
"indexOf",
|
|
||||||
"italics",
|
|
||||||
"lastIndexOf",
|
|
||||||
"match",
|
|
||||||
"replace",
|
|
||||||
"search",
|
|
||||||
"slice",
|
|
||||||
"split",
|
|
||||||
"substr",
|
|
||||||
"substring",
|
|
||||||
"trim",
|
|
||||||
].concat(object_fns),
|
|
||||||
};
|
|
||||||
convert_to_predicate(native_fns);
|
|
||||||
var static_fns = {
|
|
||||||
Array: [
|
|
||||||
"isArray",
|
|
||||||
],
|
|
||||||
Math: [
|
|
||||||
"abs",
|
|
||||||
"acos",
|
|
||||||
"asin",
|
|
||||||
"atan",
|
|
||||||
"ceil",
|
|
||||||
"cos",
|
|
||||||
"exp",
|
|
||||||
"floor",
|
|
||||||
"log",
|
|
||||||
"round",
|
|
||||||
"sin",
|
|
||||||
"sqrt",
|
|
||||||
"tan",
|
|
||||||
"atan2",
|
|
||||||
"pow",
|
|
||||||
"max",
|
|
||||||
"min"
|
|
||||||
],
|
|
||||||
Number: [
|
|
||||||
"isFinite",
|
|
||||||
"isNaN",
|
|
||||||
],
|
|
||||||
String: [
|
|
||||||
"fromCharCode",
|
|
||||||
],
|
|
||||||
};
|
|
||||||
convert_to_predicate(static_fns);
|
|
||||||
def(AST_Call, function(compressor, depth) {
|
def(AST_Call, function(compressor, depth) {
|
||||||
var exp = this.expression;
|
var exp = this.expression;
|
||||||
if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
if (compressor.option("unsafe") && exp instanceof AST_PropAccess) {
|
||||||
@@ -2443,7 +2580,16 @@ merge(Compressor.prototype, {
|
|||||||
if (arg === value) return this;
|
if (arg === value) return this;
|
||||||
args.push(value);
|
args.push(value);
|
||||||
}
|
}
|
||||||
return val[key].apply(val, args);
|
try {
|
||||||
|
return val[key].apply(val, args);
|
||||||
|
} catch (ex) {
|
||||||
|
compressor.warn("Error evaluating {code} [{file}:{line},{col}]", {
|
||||||
|
code: this.print_to_string(),
|
||||||
|
file: this.start.file,
|
||||||
|
line: this.start.line,
|
||||||
|
col: this.start.col
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
});
|
});
|
||||||
@@ -2537,9 +2683,34 @@ merge(Compressor.prototype, {
|
|||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe")) {
|
||||||
var expr = this.expression;
|
var expr = this.expression;
|
||||||
if (is_undeclared_ref(expr) && global_pure_fns(expr.name)) return true;
|
if (is_undeclared_ref(expr) && global_pure_fns(expr.name)) return true;
|
||||||
|
if (expr instanceof AST_Dot
|
||||||
|
&& is_undeclared_ref(expr.expression)
|
||||||
|
&& (static_fns[expr.expression.name] || return_false)(expr.property)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this.pure || !compressor.pure_funcs(this);
|
return this.pure || !compressor.pure_funcs(this);
|
||||||
});
|
});
|
||||||
|
AST_Node.DEFMETHOD("is_call_pure", return_false);
|
||||||
|
AST_Dot.DEFMETHOD("is_call_pure", function(compressor) {
|
||||||
|
if (!compressor.option("unsafe")) return;
|
||||||
|
var expr = this.expression;
|
||||||
|
var fns = return_false;
|
||||||
|
if (expr instanceof AST_Array) {
|
||||||
|
fns = native_fns.Array;
|
||||||
|
} else if (expr.is_boolean()) {
|
||||||
|
fns = native_fns.Boolean;
|
||||||
|
} else if (expr.is_number(compressor)) {
|
||||||
|
fns = native_fns.Number;
|
||||||
|
} else if (expr instanceof AST_RegExp) {
|
||||||
|
fns = native_fns.RegExp;
|
||||||
|
} else if (expr.is_string(compressor)) {
|
||||||
|
fns = native_fns.String;
|
||||||
|
} else if (!this.may_throw_on_access(compressor)) {
|
||||||
|
fns = native_fns.Object;
|
||||||
|
}
|
||||||
|
return fns(this.property);
|
||||||
|
});
|
||||||
|
|
||||||
// determine if expression has side effects
|
// determine if expression has side effects
|
||||||
(function(def){
|
(function(def){
|
||||||
@@ -2560,8 +2731,12 @@ merge(Compressor.prototype, {
|
|||||||
return any(this.body, compressor);
|
return any(this.body, compressor);
|
||||||
});
|
});
|
||||||
def(AST_Call, function(compressor){
|
def(AST_Call, function(compressor){
|
||||||
return !this.is_expr_pure(compressor)
|
if (!this.is_expr_pure(compressor)
|
||||||
|| any(this.args, compressor);
|
&& (!this.expression.is_call_pure(compressor)
|
||||||
|
|| this.expression.has_side_effects(compressor))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return any(this.args, compressor);
|
||||||
});
|
});
|
||||||
def(AST_Switch, function(compressor){
|
def(AST_Switch, function(compressor){
|
||||||
return this.expression.has_side_effects(compressor)
|
return this.expression.has_side_effects(compressor)
|
||||||
@@ -2952,7 +3127,7 @@ merge(Compressor.prototype, {
|
|||||||
var node_def = def.name.definition();;
|
var node_def = def.name.definition();;
|
||||||
initializations.add(node_def.id, def.value);
|
initializations.add(node_def.id, def.value);
|
||||||
if (def.name.fixed_value() === def.value) {
|
if (def.name.fixed_value() === def.value) {
|
||||||
fixed_ids[node_def.id] = true;
|
fixed_ids[node_def.id] = def;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (def.value.has_side_effects(compressor)) {
|
if (def.value.has_side_effects(compressor)) {
|
||||||
@@ -2988,9 +3163,7 @@ merge(Compressor.prototype, {
|
|||||||
var def = sym.definition();
|
var def = sym.definition();
|
||||||
var in_use = def.id in in_use_ids;
|
var in_use = def.id in in_use_ids;
|
||||||
if (node instanceof AST_Assign) {
|
if (node instanceof AST_Assign) {
|
||||||
if (!in_use
|
if (!in_use || def.id in fixed_ids && fixed_ids[def.id] !== node) {
|
||||||
|| def.id in fixed_ids
|
|
||||||
&& node.left.fixed_value() !== node.right) {
|
|
||||||
return maintain_this_binding(parent, node, node.right.transform(tt));
|
return maintain_this_binding(parent, node, node.right.transform(tt));
|
||||||
}
|
}
|
||||||
} else if (!in_use) return make_node(AST_Number, node, {
|
} else if (!in_use) return make_node(AST_Number, node, {
|
||||||
@@ -3059,25 +3232,31 @@ merge(Compressor.prototype, {
|
|||||||
var sym = def.name.definition();
|
var sym = def.name.definition();
|
||||||
if (drop_block && sym.global) return tail.push(def);
|
if (drop_block && sym.global) return tail.push(def);
|
||||||
if (!(drop_vars || drop_block) || sym.id in in_use_ids) {
|
if (!(drop_vars || drop_block) || sym.id in in_use_ids) {
|
||||||
|
if (def.value && sym.id in fixed_ids && fixed_ids[sym.id] !== def) {
|
||||||
|
def.value = def.value.drop_side_effect_free(compressor);
|
||||||
|
}
|
||||||
if (def.name instanceof AST_SymbolVar) {
|
if (def.name instanceof AST_SymbolVar) {
|
||||||
var var_defs = var_defs_by_id.get(sym.id);
|
var var_defs = var_defs_by_id.get(sym.id);
|
||||||
if (var_defs.length > 1 && (!def.value || sym.orig.indexOf(def.name) > sym.eliminated)) {
|
if (var_defs.length > 1 && (!def.value || sym.orig.indexOf(def.name) > sym.eliminated)) {
|
||||||
compressor.warn("Dropping duplicated definition of variable {name} [{file}:{line},{col}]", template(def.name));
|
compressor.warn("Dropping duplicated definition of variable {name} [{file}:{line},{col}]", template(def.name));
|
||||||
if (def.value) {
|
if (def.value) {
|
||||||
side_effects.push(make_node(AST_Assign, def, {
|
var ref = make_node(AST_SymbolRef, def.name, def.name);
|
||||||
|
sym.references.push(ref);
|
||||||
|
var assign = make_node(AST_Assign, def, {
|
||||||
operator: "=",
|
operator: "=",
|
||||||
left: make_node(AST_SymbolRef, def.name, def.name),
|
left: ref,
|
||||||
right: def.value
|
right: def.value
|
||||||
}).transform(tt));
|
});
|
||||||
|
if (fixed_ids[sym.id] === def) {
|
||||||
|
fixed_ids[sym.id] = assign;
|
||||||
|
}
|
||||||
|
side_effects.push(assign.transform(tt));
|
||||||
}
|
}
|
||||||
remove(var_defs, def);
|
remove(var_defs, def);
|
||||||
sym.eliminated++;
|
sym.eliminated++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (def.value && sym.id in fixed_ids && def.name.fixed_value() !== def.value) {
|
|
||||||
def.value = def.value.drop_side_effect_free(compressor);
|
|
||||||
}
|
|
||||||
if (def.value) {
|
if (def.value) {
|
||||||
if (side_effects.length > 0) {
|
if (side_effects.length > 0) {
|
||||||
if (tail.length > 0) {
|
if (tail.length > 0) {
|
||||||
@@ -3196,7 +3375,7 @@ merge(Compressor.prototype, {
|
|||||||
if (node instanceof AST_Assign) {
|
if (node instanceof AST_Assign) {
|
||||||
node.right.walk(tw);
|
node.right.walk(tw);
|
||||||
if (node.left.fixed_value() === node.right) {
|
if (node.left.fixed_value() === node.right) {
|
||||||
fixed_ids[node_def.id] = true;
|
fixed_ids[node_def.id] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -3415,9 +3594,7 @@ merge(Compressor.prototype, {
|
|||||||
if (node instanceof AST_PropAccess && node.expression instanceof AST_SymbolRef) {
|
if (node instanceof AST_PropAccess && node.expression instanceof AST_SymbolRef) {
|
||||||
var defs = defs_by_id[node.expression.definition().id];
|
var defs = defs_by_id[node.expression.definition().id];
|
||||||
if (defs) {
|
if (defs) {
|
||||||
var key = node.property;
|
var def = defs.get(get_value(node.property));
|
||||||
if (key instanceof AST_Node) key = key.getValue();
|
|
||||||
var def = defs.get(key);
|
|
||||||
var sym = make_node(AST_SymbolRef, node, {
|
var sym = make_node(AST_SymbolRef, node, {
|
||||||
name: def.name,
|
name: def.name,
|
||||||
scope: node.expression.scope,
|
scope: node.expression.scope,
|
||||||
@@ -3469,6 +3646,12 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_This, return_null);
|
def(AST_This, return_null);
|
||||||
def(AST_Call, function(compressor, first_in_statement){
|
def(AST_Call, function(compressor, first_in_statement){
|
||||||
if (!this.is_expr_pure(compressor)) {
|
if (!this.is_expr_pure(compressor)) {
|
||||||
|
if (this.expression.is_call_pure(compressor)) {
|
||||||
|
var exprs = this.args.slice();
|
||||||
|
exprs.unshift(this.expression.expression);
|
||||||
|
exprs = trim(exprs, compressor, first_in_statement);
|
||||||
|
return exprs && make_sequence(this, exprs);
|
||||||
|
}
|
||||||
if (is_func_expr(this.expression)
|
if (is_func_expr(this.expression)
|
||||||
&& (!this.expression.name || !this.expression.name.definition().references.length)) {
|
&& (!this.expression.name || !this.expression.name.definition().references.length)) {
|
||||||
var node = this.clone();
|
var node = this.clone();
|
||||||
@@ -3513,8 +3696,10 @@ merge(Compressor.prototype, {
|
|||||||
while (left instanceof AST_PropAccess) {
|
while (left instanceof AST_PropAccess) {
|
||||||
left = left.expression;
|
left = left.expression;
|
||||||
}
|
}
|
||||||
if (left instanceof AST_Symbol) return this;
|
if (left.is_constant_expression(compressor.find_parent(AST_Scope))) {
|
||||||
return this.right.drop_side_effect_free(compressor);
|
return this.right.drop_side_effect_free(compressor);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
});
|
});
|
||||||
def(AST_Conditional, function(compressor){
|
def(AST_Conditional, function(compressor){
|
||||||
var consequent = this.consequent.drop_side_effect_free(compressor);
|
var consequent = this.consequent.drop_side_effect_free(compressor);
|
||||||
@@ -3648,23 +3833,28 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function if_break_in_loop(self, compressor) {
|
function if_break_in_loop(self, compressor) {
|
||||||
function drop_it(rest) {
|
|
||||||
rest = as_statement_array(rest);
|
|
||||||
if (self.body instanceof AST_BlockStatement) {
|
|
||||||
self.body = self.body.clone();
|
|
||||||
self.body.body = rest.concat(self.body.body.slice(1));
|
|
||||||
self.body = self.body.transform(compressor);
|
|
||||||
} else {
|
|
||||||
self.body = make_node(AST_BlockStatement, self.body, {
|
|
||||||
body: rest
|
|
||||||
}).transform(compressor);
|
|
||||||
}
|
|
||||||
if_break_in_loop(self, compressor);
|
|
||||||
}
|
|
||||||
var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
|
var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
|
||||||
|
if (compressor.option("dead_code") && is_break(first)) {
|
||||||
|
var body = [];
|
||||||
|
if (self.init instanceof AST_Statement) {
|
||||||
|
body.push(self.init);
|
||||||
|
} else if (self.init) {
|
||||||
|
body.push(make_node(AST_SimpleStatement, self.init, {
|
||||||
|
body: self.init
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
if (self.condition) {
|
||||||
|
body.push(make_node(AST_SimpleStatement, self.condition, {
|
||||||
|
body: self.condition
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
extract_declarations_from_unreachable_code(compressor, self.body, body);
|
||||||
|
return make_node(AST_BlockStatement, self, {
|
||||||
|
body: body
|
||||||
|
});
|
||||||
|
}
|
||||||
if (first instanceof AST_If) {
|
if (first instanceof AST_If) {
|
||||||
if (first.body instanceof AST_Break
|
if (is_break(first.body)) {
|
||||||
&& compressor.loopcontrol_target(first.body) === compressor.self()) {
|
|
||||||
if (self.condition) {
|
if (self.condition) {
|
||||||
self.condition = make_node(AST_Binary, self.condition, {
|
self.condition = make_node(AST_Binary, self.condition, {
|
||||||
left: self.condition,
|
left: self.condition,
|
||||||
@@ -3675,9 +3865,7 @@ merge(Compressor.prototype, {
|
|||||||
self.condition = first.condition.negate(compressor);
|
self.condition = first.condition.negate(compressor);
|
||||||
}
|
}
|
||||||
drop_it(first.alternative);
|
drop_it(first.alternative);
|
||||||
}
|
} else if (is_break(first.alternative)) {
|
||||||
else if (first.alternative instanceof AST_Break
|
|
||||||
&& compressor.loopcontrol_target(first.alternative) === compressor.self()) {
|
|
||||||
if (self.condition) {
|
if (self.condition) {
|
||||||
self.condition = make_node(AST_Binary, self.condition, {
|
self.condition = make_node(AST_Binary, self.condition, {
|
||||||
left: self.condition,
|
left: self.condition,
|
||||||
@@ -3690,7 +3878,27 @@ merge(Compressor.prototype, {
|
|||||||
drop_it(first.body);
|
drop_it(first.body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
return self;
|
||||||
|
|
||||||
|
function is_break(node) {
|
||||||
|
return node instanceof AST_Break
|
||||||
|
&& compressor.loopcontrol_target(node) === compressor.self();
|
||||||
|
}
|
||||||
|
|
||||||
|
function drop_it(rest) {
|
||||||
|
rest = as_statement_array(rest);
|
||||||
|
if (self.body instanceof AST_BlockStatement) {
|
||||||
|
self.body = self.body.clone();
|
||||||
|
self.body.body = rest.concat(self.body.body.slice(1));
|
||||||
|
self.body = self.body.transform(compressor);
|
||||||
|
} else {
|
||||||
|
self.body = make_node(AST_BlockStatement, self.body, {
|
||||||
|
body: rest
|
||||||
|
}).transform(compressor);
|
||||||
|
}
|
||||||
|
self = if_break_in_loop(self, compressor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OPT(AST_For, function(self, compressor){
|
OPT(AST_For, function(self, compressor){
|
||||||
if (!compressor.option("loops")) return self;
|
if (!compressor.option("loops")) return self;
|
||||||
@@ -3726,8 +3934,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if_break_in_loop(self, compressor);
|
return if_break_in_loop(self, compressor);
|
||||||
return self;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
OPT(AST_If, function(self, compressor){
|
OPT(AST_If, function(self, compressor){
|
||||||
@@ -3983,9 +4190,20 @@ merge(Compressor.prototype, {
|
|||||||
OPT(AST_Try, function(self, compressor){
|
OPT(AST_Try, function(self, compressor){
|
||||||
tighten_body(self.body, compressor);
|
tighten_body(self.body, compressor);
|
||||||
if (self.bcatch && self.bfinally && all(self.bfinally.body, is_empty)) self.bfinally = null;
|
if (self.bcatch && self.bfinally && all(self.bfinally.body, is_empty)) self.bfinally = null;
|
||||||
if (all(self.body, is_empty)) {
|
if (compressor.option("dead_code") && all(self.body, is_empty)) {
|
||||||
var body = [];
|
var body = [];
|
||||||
if (self.bcatch) extract_declarations_from_unreachable_code(compressor, self.bcatch, body);
|
if (self.bcatch) {
|
||||||
|
extract_declarations_from_unreachable_code(compressor, self.bcatch, body);
|
||||||
|
body.forEach(function(stat) {
|
||||||
|
if (!(stat instanceof AST_Definitions)) return;
|
||||||
|
stat.definitions.forEach(function(var_def) {
|
||||||
|
var def = var_def.name.definition().redefined();
|
||||||
|
if (!def) return;
|
||||||
|
var_def.name = var_def.name.clone();
|
||||||
|
var_def.name.thedef = def;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
if (self.bfinally) body = body.concat(self.bfinally.body);
|
if (self.bfinally) body = body.concat(self.bfinally.body);
|
||||||
return make_node(AST_BlockStatement, self, {
|
return make_node(AST_BlockStatement, self, {
|
||||||
body: body
|
body: body
|
||||||
@@ -4171,11 +4389,13 @@ merge(Compressor.prototype, {
|
|||||||
return self;
|
return self;
|
||||||
} else if (exp instanceof AST_Dot) switch(exp.property) {
|
} else if (exp instanceof AST_Dot) switch(exp.property) {
|
||||||
case "toString":
|
case "toString":
|
||||||
if (self.args.length == 0) return make_node(AST_Binary, self, {
|
if (self.args.length == 0 && !exp.expression.may_throw_on_access(compressor)) {
|
||||||
left: make_node(AST_String, self, { value: "" }),
|
return make_node(AST_Binary, self, {
|
||||||
operator: "+",
|
left: make_node(AST_String, self, { value: "" }),
|
||||||
right: exp.expression
|
operator: "+",
|
||||||
}).optimize(compressor);
|
right: exp.expression
|
||||||
|
}).optimize(compressor);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case "join":
|
case "join":
|
||||||
if (exp.expression instanceof AST_Array) EXIT: {
|
if (exp.expression instanceof AST_Array) EXIT: {
|
||||||
@@ -4285,7 +4505,7 @@ merge(Compressor.prototype, {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("unsafe_Func")
|
if (compressor.option("unsafe_Function")
|
||||||
&& is_undeclared_ref(exp)
|
&& is_undeclared_ref(exp)
|
||||||
&& exp.name == "Function") {
|
&& exp.name == "Function") {
|
||||||
// new Function() => function(){}
|
// new Function() => function(){}
|
||||||
@@ -5238,6 +5458,7 @@ merge(Compressor.prototype, {
|
|||||||
fixed = make_node(AST_ClassExpression, fixed, fixed);
|
fixed = make_node(AST_ClassExpression, fixed, fixed);
|
||||||
}
|
}
|
||||||
if (fixed instanceof AST_Defun) {
|
if (fixed instanceof AST_Defun) {
|
||||||
|
fixed._squeezed = true;
|
||||||
fixed = make_node(AST_Function, fixed, fixed);
|
fixed = make_node(AST_Function, fixed, fixed);
|
||||||
}
|
}
|
||||||
var value;
|
var value;
|
||||||
@@ -5325,7 +5546,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
|
|
||||||
OPT(AST_Undefined, function(self, compressor){
|
OPT(AST_Undefined, function(self, compressor){
|
||||||
if (compressor.option("unsafe")) {
|
if (compressor.option("unsafe_undefined")) {
|
||||||
var undef = find_variable(compressor, "undefined");
|
var undef = find_variable(compressor, "undefined");
|
||||||
if (undef) {
|
if (undef) {
|
||||||
var ref = make_node(AST_SymbolRef, self, {
|
var ref = make_node(AST_SymbolRef, self, {
|
||||||
@@ -5576,6 +5797,20 @@ merge(Compressor.prototype, {
|
|||||||
consequent
|
consequent
|
||||||
]).optimize(compressor);
|
]).optimize(compressor);
|
||||||
}
|
}
|
||||||
|
// x ? y || z : z --> x && y || z
|
||||||
|
if (consequent instanceof AST_Binary
|
||||||
|
&& consequent.operator == "||"
|
||||||
|
&& consequent.right.equivalent_to(alternative)) {
|
||||||
|
return make_node(AST_Binary, self, {
|
||||||
|
operator: "||",
|
||||||
|
left: make_node(AST_Binary, self, {
|
||||||
|
operator: "&&",
|
||||||
|
left: self.condition,
|
||||||
|
right: consequent.left
|
||||||
|
}),
|
||||||
|
right: alternative
|
||||||
|
}).optimize(compressor);
|
||||||
|
}
|
||||||
var in_bool = compressor.in_boolean_context();
|
var in_bool = compressor.in_boolean_context();
|
||||||
if (is_true(self.consequent)) {
|
if (is_true(self.consequent)) {
|
||||||
if (is_false(self.alternative)) {
|
if (is_false(self.alternative)) {
|
||||||
@@ -5841,6 +6076,7 @@ merge(Compressor.prototype, {
|
|||||||
if (def) {
|
if (def) {
|
||||||
return def.optimize(compressor);
|
return def.optimize(compressor);
|
||||||
}
|
}
|
||||||
|
if (is_lhs(self, compressor.parent())) return self;
|
||||||
if (compressor.option("unsafe_proto")
|
if (compressor.option("unsafe_proto")
|
||||||
&& self.expression instanceof AST_Dot
|
&& self.expression instanceof AST_Dot
|
||||||
&& self.expression.property == "prototype") {
|
&& self.expression.property == "prototype") {
|
||||||
@@ -5879,7 +6115,6 @@ merge(Compressor.prototype, {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (is_lhs(self, compressor.parent())) return self;
|
|
||||||
var sub = self.flatten_object(self.property, compressor);
|
var sub = self.flatten_object(self.property, compressor);
|
||||||
if (sub) return sub.optimize(compressor);
|
if (sub) return sub.optimize(compressor);
|
||||||
var ev = self.evaluate(compressor);
|
var ev = self.evaluate(compressor);
|
||||||
|
|||||||
@@ -151,7 +151,9 @@ function minify(files, options) {
|
|||||||
toplevel = toplevel.wrap_commonjs(options.wrap);
|
toplevel = toplevel.wrap_commonjs(options.wrap);
|
||||||
}
|
}
|
||||||
if (timings) timings.rename = Date.now();
|
if (timings) timings.rename = Date.now();
|
||||||
if (options.rename) {
|
// disable rename on harmony due to expand_names bug in for-of loops
|
||||||
|
// https://github.com/mishoo/UglifyJS2/issues/2794
|
||||||
|
if (0 && options.rename) {
|
||||||
toplevel.figure_out_scope(options.mangle);
|
toplevel.figure_out_scope(options.mangle);
|
||||||
toplevel.expand_names(options.mangle);
|
toplevel.expand_names(options.mangle);
|
||||||
}
|
}
|
||||||
|
|||||||
201
lib/output.js
201
lib/output.js
@@ -472,83 +472,87 @@ function OutputStream(options) {
|
|||||||
return OUTPUT;
|
return OUTPUT;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function has_nlb() {
|
||||||
|
var index = OUTPUT.lastIndexOf("\n");
|
||||||
|
return /^ *$/.test(OUTPUT.slice(index + 1));
|
||||||
|
}
|
||||||
|
|
||||||
function prepend_comments(node) {
|
function prepend_comments(node) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var start = node.start;
|
var start = node.start;
|
||||||
if (!start) return;
|
if (!start) return;
|
||||||
if (!(start.comments_before && start.comments_before._dumped === self)) {
|
if (start.comments_before && start.comments_before._dumped === self) return;
|
||||||
var comments = start.comments_before;
|
var comments = start.comments_before;
|
||||||
if (!comments) {
|
if (!comments) {
|
||||||
comments = start.comments_before = [];
|
comments = start.comments_before = [];
|
||||||
}
|
}
|
||||||
comments._dumped = self;
|
comments._dumped = self;
|
||||||
|
|
||||||
if (node instanceof AST_Exit && node.value) {
|
if (node instanceof AST_Exit && node.value) {
|
||||||
var tw = new TreeWalker(function(node) {
|
var tw = new TreeWalker(function(node) {
|
||||||
var parent = tw.parent();
|
var parent = tw.parent();
|
||||||
if (parent instanceof AST_Exit
|
if (parent instanceof AST_Exit
|
||||||
|| parent instanceof AST_Binary && parent.left === node
|
|| parent instanceof AST_Binary && parent.left === node
|
||||||
|| parent.TYPE == "Call" && parent.expression === node
|
|| parent.TYPE == "Call" && parent.expression === node
|
||||||
|| parent instanceof AST_Conditional && parent.condition === node
|
|| parent instanceof AST_Conditional && parent.condition === node
|
||||||
|| parent instanceof AST_Dot && parent.expression === node
|
|| parent instanceof AST_Dot && parent.expression === node
|
||||||
|| parent instanceof AST_Sequence && parent.expressions[0] === node
|
|| parent instanceof AST_Sequence && parent.expressions[0] === node
|
||||||
|| parent instanceof AST_Sub && parent.expression === node
|
|| parent instanceof AST_Sub && parent.expression === node
|
||||||
|| parent instanceof AST_UnaryPostfix) {
|
|| parent instanceof AST_UnaryPostfix) {
|
||||||
if (!node.start) return;
|
if (!node.start) return;
|
||||||
var text = node.start.comments_before;
|
var text = node.start.comments_before;
|
||||||
if (text && text._dumped !== self) {
|
if (text && text._dumped !== self) {
|
||||||
text._dumped = self;
|
text._dumped = self;
|
||||||
comments = comments.concat(text);
|
comments = comments.concat(text);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
});
|
} else {
|
||||||
tw.push(node);
|
return true;
|
||||||
node.value.walk(tw);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current_pos == 0) {
|
|
||||||
if (comments.length > 0 && options.shebang && comments[0].type == "comment5") {
|
|
||||||
print("#!" + comments.shift().value + "\n");
|
|
||||||
indent();
|
|
||||||
}
|
|
||||||
var preamble = options.preamble;
|
|
||||||
if (preamble) {
|
|
||||||
print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
comments = comments.filter(comment_filter, node);
|
|
||||||
if (comments.length == 0) return;
|
|
||||||
var last_nlb = /(^|\n) *$/.test(OUTPUT);
|
|
||||||
comments.forEach(function(c, i) {
|
|
||||||
if (!last_nlb) {
|
|
||||||
if (c.nlb) {
|
|
||||||
print("\n");
|
|
||||||
indent();
|
|
||||||
last_nlb = true;
|
|
||||||
} else if (i > 0) {
|
|
||||||
space();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (/comment[134]/.test(c.type)) {
|
|
||||||
print("//" + c.value.replace(/[@#]__PURE__/g, ' ') + "\n");
|
|
||||||
indent();
|
|
||||||
last_nlb = true;
|
|
||||||
} else if (c.type == "comment2") {
|
|
||||||
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
|
|
||||||
last_nlb = false;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
tw.push(node);
|
||||||
|
node.value.walk(tw);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_pos == 0) {
|
||||||
|
if (comments.length > 0 && options.shebang && comments[0].type == "comment5") {
|
||||||
|
print("#!" + comments.shift().value + "\n");
|
||||||
|
indent();
|
||||||
|
}
|
||||||
|
var preamble = options.preamble;
|
||||||
|
if (preamble) {
|
||||||
|
print(preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
comments = comments.filter(comment_filter, node);
|
||||||
|
if (comments.length == 0) return;
|
||||||
|
var last_nlb = has_nlb();
|
||||||
|
comments.forEach(function(c, i) {
|
||||||
if (!last_nlb) {
|
if (!last_nlb) {
|
||||||
if (start.nlb) {
|
if (c.nlb) {
|
||||||
print("\n");
|
print("\n");
|
||||||
indent();
|
indent();
|
||||||
} else {
|
last_nlb = true;
|
||||||
|
} else if (i > 0) {
|
||||||
space();
|
space();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (/comment[134]/.test(c.type)) {
|
||||||
|
print("//" + c.value.replace(/[@#]__PURE__/g, ' ') + "\n");
|
||||||
|
indent();
|
||||||
|
last_nlb = true;
|
||||||
|
} else if (c.type == "comment2") {
|
||||||
|
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
|
||||||
|
last_nlb = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (!last_nlb) {
|
||||||
|
if (start.nlb) {
|
||||||
|
print("\n");
|
||||||
|
indent();
|
||||||
|
} else {
|
||||||
|
space();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,35 +561,33 @@ function OutputStream(options) {
|
|||||||
var token = node.end;
|
var token = node.end;
|
||||||
if (!token) return;
|
if (!token) return;
|
||||||
var comments = token[tail ? "comments_before" : "comments_after"];
|
var comments = token[tail ? "comments_before" : "comments_after"];
|
||||||
if (comments
|
if (!comments || comments._dumped === self) return;
|
||||||
&& comments._dumped !== self
|
if (!(node instanceof AST_Statement || all(comments, function(c) {
|
||||||
&& (node instanceof AST_Statement || all(comments, function(c) {
|
return !/comment[134]/.test(c.type);
|
||||||
return !/comment[134]/.test(c.type);
|
}))) return;
|
||||||
}))) {
|
comments._dumped = self;
|
||||||
comments._dumped = self;
|
var insert = OUTPUT.length;
|
||||||
var insert = OUTPUT.length;
|
comments.filter(comment_filter, node).forEach(function(c, i) {
|
||||||
comments.filter(comment_filter, node).forEach(function(c, i) {
|
need_space = false;
|
||||||
need_space = false;
|
if (need_newline_indented) {
|
||||||
if (need_newline_indented) {
|
print("\n");
|
||||||
print("\n");
|
indent();
|
||||||
indent();
|
need_newline_indented = false;
|
||||||
need_newline_indented = false;
|
} else if (c.nlb && (i > 0 || !has_nlb())) {
|
||||||
} else if (c.nlb && (i > 0 || !/(^|\n) *$/.test(OUTPUT))) {
|
print("\n");
|
||||||
print("\n");
|
indent();
|
||||||
indent();
|
} else if (i > 0 || !tail) {
|
||||||
} else if (i > 0 || !tail) {
|
space();
|
||||||
space();
|
}
|
||||||
}
|
if (/comment[134]/.test(c.type)) {
|
||||||
if (/comment[134]/.test(c.type)) {
|
print("//" + c.value.replace(/[@#]__PURE__/g, ' '));
|
||||||
print("//" + c.value.replace(/[@#]__PURE__/g, ' '));
|
need_newline_indented = true;
|
||||||
need_newline_indented = true;
|
} else if (c.type == "comment2") {
|
||||||
} else if (c.type == "comment2") {
|
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
|
||||||
print("/*" + c.value.replace(/[@#]__PURE__/g, ' ') + "*/");
|
need_space = true;
|
||||||
need_space = true;
|
}
|
||||||
}
|
});
|
||||||
});
|
if (OUTPUT.length > insert) newline_insert = insert;
|
||||||
if (OUTPUT.length > insert) newline_insert = insert;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var stack = [];
|
var stack = [];
|
||||||
@@ -769,6 +771,8 @@ function OutputStream(options) {
|
|||||||
|| p instanceof AST_Arrow // x => (x, x)
|
|| p instanceof AST_Arrow // x => (x, x)
|
||||||
|| p instanceof AST_DefaultAssign // x => (x = (0, function(){}))
|
|| p instanceof AST_DefaultAssign // x => (x = (0, function(){}))
|
||||||
|| p instanceof AST_Expansion // [...(a, b)]
|
|| p instanceof AST_Expansion // [...(a, b)]
|
||||||
|
|| p instanceof AST_ForOf && this === p.object // for (e of (foo, bar)) {}
|
||||||
|
|| p instanceof AST_Yield // yield (foo, bar)
|
||||||
;
|
;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1049,11 +1053,7 @@ function OutputStream(options) {
|
|||||||
output.with_parens(function(){
|
output.with_parens(function(){
|
||||||
self.init.print(output);
|
self.init.print(output);
|
||||||
output.space();
|
output.space();
|
||||||
if (self instanceof AST_ForOf) {
|
output.print(self instanceof AST_ForOf ? "of" : "in");
|
||||||
output.print("of");
|
|
||||||
} else {
|
|
||||||
output.print("in");
|
|
||||||
}
|
|
||||||
output.space();
|
output.space();
|
||||||
self.object.print(output);
|
self.object.print(output);
|
||||||
});
|
});
|
||||||
@@ -1683,11 +1683,8 @@ function OutputStream(options) {
|
|||||||
|
|
||||||
function print_property_name(key, quote, output) {
|
function print_property_name(key, quote, output) {
|
||||||
if (output.option("quote_keys")) {
|
if (output.option("quote_keys")) {
|
||||||
output.print_string(key + "");
|
output.print_string(key);
|
||||||
} else if ((typeof key == "number"
|
} else if ("" + +key == key && key >= 0) {
|
||||||
|| !output.option("beautify")
|
|
||||||
&& +key + "" == key)
|
|
||||||
&& parseFloat(key) >= 0) {
|
|
||||||
output.print(make_num(key));
|
output.print(make_num(key));
|
||||||
} else if (RESERVED_WORDS(key) ? !output.option("ie8") : is_identifier_string(key)) {
|
} else if (RESERVED_WORDS(key) ? !output.option("ie8") : is_identifier_string(key)) {
|
||||||
if (quote && output.option("keep_quoted_props")) {
|
if (quote && output.option("keep_quoted_props")) {
|
||||||
|
|||||||
@@ -1276,12 +1276,10 @@ function parse($TEXT, options) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function for_in(init) {
|
function for_in(init) {
|
||||||
var lhs = init instanceof AST_Definitions ? init.definitions[0].name : null;
|
|
||||||
var obj = expression(true);
|
var obj = expression(true);
|
||||||
expect(")");
|
expect(")");
|
||||||
return new AST_ForIn({
|
return new AST_ForIn({
|
||||||
init : init,
|
init : init,
|
||||||
name : lhs,
|
|
||||||
object : obj,
|
object : obj,
|
||||||
body : in_loop(statement)
|
body : in_loop(statement)
|
||||||
});
|
});
|
||||||
@@ -1862,7 +1860,7 @@ function parse($TEXT, options) {
|
|||||||
name : as_symbol(sym_type),
|
name : as_symbol(sym_type),
|
||||||
value : is("operator", "=")
|
value : is("operator", "=")
|
||||||
? (next(), expression(false, no_in))
|
? (next(), expression(false, no_in))
|
||||||
: !no_in && kind === "const" && S.input.has_directive("use strict")
|
: !no_in && kind === "const"
|
||||||
? croak("Missing initializer in const declaration") : null,
|
? croak("Missing initializer in const declaration") : null,
|
||||||
end : prev()
|
end : prev()
|
||||||
});
|
});
|
||||||
@@ -2226,7 +2224,7 @@ function parse($TEXT, options) {
|
|||||||
a.push(new AST_ObjectKeyVal({
|
a.push(new AST_ObjectKeyVal({
|
||||||
start: start,
|
start: start,
|
||||||
quote: start.quote,
|
quote: start.quote,
|
||||||
key: name,
|
key: name instanceof AST_Node ? name : "" + name,
|
||||||
value: value,
|
value: value,
|
||||||
end: prev()
|
end: prev()
|
||||||
}));
|
}));
|
||||||
@@ -2283,7 +2281,7 @@ function parse($TEXT, options) {
|
|||||||
if (typeof name === "string" || typeof name === "number") {
|
if (typeof name === "string" || typeof name === "number") {
|
||||||
return new AST_SymbolMethod({
|
return new AST_SymbolMethod({
|
||||||
start: token,
|
start: token,
|
||||||
name: name,
|
name: "" + name,
|
||||||
end: prev()
|
end: prev()
|
||||||
});
|
});
|
||||||
} else if (name === null) {
|
} else if (name === null) {
|
||||||
|
|||||||
65
lib/scope.js
65
lib/scope.js
@@ -202,7 +202,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options){
|
|||||||
|| node instanceof AST_SymbolConst) {
|
|| node instanceof AST_SymbolConst) {
|
||||||
var def;
|
var def;
|
||||||
if (node instanceof AST_SymbolBlockDeclaration) {
|
if (node instanceof AST_SymbolBlockDeclaration) {
|
||||||
def = scope.def_variable(node);
|
def = scope.def_variable(node, null);
|
||||||
} else {
|
} else {
|
||||||
def = defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
|
def = defun.def_variable(node, node.TYPE == "SymbolVar" ? null : undefined);
|
||||||
}
|
}
|
||||||
@@ -411,7 +411,7 @@ AST_Scope.DEFMETHOD("find_variable", function(name){
|
|||||||
|
|
||||||
AST_Scope.DEFMETHOD("def_function", function(symbol, init){
|
AST_Scope.DEFMETHOD("def_function", function(symbol, init){
|
||||||
var def = this.def_variable(symbol, init);
|
var def = this.def_variable(symbol, init);
|
||||||
if (!def.init) def.init = init;
|
if (!def.init || def.init instanceof AST_Defun) def.init = init;
|
||||||
this.functions.set(symbol.name, def);
|
this.functions.set(symbol.name, def);
|
||||||
return def;
|
return def;
|
||||||
});
|
});
|
||||||
@@ -550,24 +550,23 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
|||||||
node.variables.each(collect);
|
node.variables.each(collect);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (node.is_block_scope()) {
|
||||||
|
node.block_scope.variables.each(collect);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (node instanceof AST_Label) {
|
if (node instanceof AST_Label) {
|
||||||
var name;
|
var name;
|
||||||
do name = base54(++lname); while (!is_identifier(name));
|
do name = base54(++lname); while (!is_identifier(name));
|
||||||
node.mangled_name = name;
|
node.mangled_name = name;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
var mangle_with_block_scope =
|
if (!options.ie8 && node instanceof AST_SymbolCatch) {
|
||||||
(!options.ie8 && node instanceof AST_SymbolCatch) ||
|
|
||||||
node instanceof AST_SymbolBlockDeclaration;
|
|
||||||
if (mangle_with_block_scope && options.reserved.indexOf(node.name) < 0) {
|
|
||||||
to_mangle.push(node.definition());
|
to_mangle.push(node.definition());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.walk(tw);
|
this.walk(tw);
|
||||||
to_mangle.forEach(function(def){
|
to_mangle.forEach(function(def){ def.mangle(options) });
|
||||||
def.mangle(options);
|
|
||||||
});
|
|
||||||
|
|
||||||
function collect(symbol) {
|
function collect(symbol) {
|
||||||
if (!member(symbol.name, options.reserved)) {
|
if (!member(symbol.name, options.reserved)) {
|
||||||
@@ -576,59 +575,55 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("find_unique_prefix", function(options) {
|
AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) {
|
||||||
var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_";
|
|
||||||
var cache = options.cache && options.cache.props;
|
var cache = options.cache && options.cache.props;
|
||||||
var prefixes = Object.create(null);
|
var avoid = Object.create(null);
|
||||||
options.reserved.forEach(add_prefix);
|
options.reserved.forEach(to_avoid);
|
||||||
this.globals.each(add_def);
|
this.globals.each(add_def);
|
||||||
this.walk(new TreeWalker(function(node) {
|
this.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Scope) node.variables.each(add_def);
|
if (node instanceof AST_Scope) node.variables.each(add_def);
|
||||||
if (node instanceof AST_SymbolCatch) add_def(node.definition());
|
if (node instanceof AST_SymbolCatch) add_def(node.definition());
|
||||||
}));
|
}));
|
||||||
var prefix, i = 0;
|
return avoid;
|
||||||
do {
|
|
||||||
prefix = create_name(i++);
|
|
||||||
} while (prefixes[prefix]);
|
|
||||||
return prefix;
|
|
||||||
|
|
||||||
function add_prefix(name) {
|
function to_avoid(name) {
|
||||||
if (/[0-9]$/.test(name)) {
|
avoid[name] = true;
|
||||||
prefixes[name.replace(/[0-9]+$/, "")] = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function add_def(def) {
|
function add_def(def) {
|
||||||
var name = def.name;
|
var name = def.name;
|
||||||
if (def.global && cache && cache.has(name)) name = cache.get(name);
|
if (def.global && cache && cache.has(name)) name = cache.get(name);
|
||||||
else if (!def.unmangleable(options)) return;
|
else if (!def.unmangleable(options)) return;
|
||||||
add_prefix(name);
|
to_avoid(name);
|
||||||
}
|
|
||||||
|
|
||||||
function create_name(num) {
|
|
||||||
var name = "";
|
|
||||||
do {
|
|
||||||
name += letters[num % letters.length];
|
|
||||||
num = Math.floor(num / letters.length);
|
|
||||||
} while (num);
|
|
||||||
return name;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
AST_Toplevel.DEFMETHOD("expand_names", function(options) {
|
||||||
|
base54.reset();
|
||||||
|
base54.sort();
|
||||||
options = this._default_mangler_options(options);
|
options = this._default_mangler_options(options);
|
||||||
var prefix = this.find_unique_prefix(options);
|
var avoid = this.find_colliding_names(options);
|
||||||
|
var cname = 0;
|
||||||
this.globals.each(rename);
|
this.globals.each(rename);
|
||||||
this.walk(new TreeWalker(function(node) {
|
this.walk(new TreeWalker(function(node) {
|
||||||
if (node instanceof AST_Scope) node.variables.each(rename);
|
if (node instanceof AST_Scope) node.variables.each(rename);
|
||||||
if (node instanceof AST_SymbolCatch) rename(node.definition());
|
if (node instanceof AST_SymbolCatch) rename(node.definition());
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
function next_name() {
|
||||||
|
var name;
|
||||||
|
do {
|
||||||
|
name = base54(cname++);
|
||||||
|
} while (avoid[name] || !is_identifier(name));
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
function rename(def) {
|
function rename(def) {
|
||||||
if (def.global || def.unmangleable(options)) return;
|
if (def.global && options.cache) return;
|
||||||
|
if (def.unmangleable(options)) return;
|
||||||
if (member(def.name, options.reserved)) return;
|
if (member(def.name, options.reserved)) return;
|
||||||
var d = def.redefined();
|
var d = def.redefined();
|
||||||
def.name = d ? d.name : prefix + def.id;
|
def.name = d ? d.name : next_name();
|
||||||
def.orig.forEach(function(sym) {
|
def.orig.forEach(function(sym) {
|
||||||
sym.name = def.name;
|
sym.name = def.name;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -303,6 +303,13 @@ Dictionary.prototype = {
|
|||||||
ret.push(f(this._values[i], i.substr(1)));
|
ret.push(f(this._values[i], i.substr(1)));
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
|
clone: function() {
|
||||||
|
var ret = new Dictionary();
|
||||||
|
for (var i in this._values)
|
||||||
|
ret._values[i] = this._values[i];
|
||||||
|
ret._size = this._size;
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
toObject: function() { return this._values }
|
toObject: function() { return this._values }
|
||||||
};
|
};
|
||||||
Dictionary.fromObject = function(obj) {
|
Dictionary.fromObject = function(obj) {
|
||||||
|
|||||||
12
package.json
12
package.json
@@ -4,17 +4,15 @@
|
|||||||
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.3.5",
|
"version": "3.3.9",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
"maintainers": [
|
"maintainers": [
|
||||||
|
"Alex Lam <alexlamsl@gmail.com>",
|
||||||
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
|
"Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)"
|
||||||
],
|
],
|
||||||
"repository": "git+https://github.com/mishoo/UglifyJS2.git#harmony",
|
"repository": "https://github.com/mishoo/UglifyJS2.git#harmony",
|
||||||
"bugs": {
|
|
||||||
"url": "https://github.com/mishoo/UglifyJS2/issues"
|
|
||||||
},
|
|
||||||
"main": "tools/node.js",
|
"main": "tools/node.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
"uglifyjs": "bin/uglifyjs"
|
"uglifyjs": "bin/uglifyjs"
|
||||||
@@ -26,11 +24,11 @@
|
|||||||
"LICENSE"
|
"LICENSE"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"commander": "~2.12.1",
|
"commander": "~2.13.0",
|
||||||
"source-map": "~0.6.1"
|
"source-map": "~0.6.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"acorn": "~5.2.1",
|
"acorn": "~5.3.0",
|
||||||
"mocha": "~3.5.1",
|
"mocha": "~3.5.1",
|
||||||
"semver": "~5.4.1"
|
"semver": "~5.4.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ do_not_remove_anon_blocks_if_they_have_decls: {
|
|||||||
var x;
|
var x;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const y;
|
const y = 1;
|
||||||
class Zee {};
|
class Zee {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,7 @@ do_not_remove_anon_blocks_if_they_have_decls: {
|
|||||||
}
|
}
|
||||||
var x;
|
var x;
|
||||||
{
|
{
|
||||||
const y;
|
const y = 1;
|
||||||
class Zee {}
|
class Zee {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,12 +77,12 @@ remove_unused_in_global_block: {
|
|||||||
input: {
|
input: {
|
||||||
{
|
{
|
||||||
let x;
|
let x;
|
||||||
const y;
|
const y = 1;
|
||||||
class Zee {};
|
class Zee {};
|
||||||
var w;
|
var w;
|
||||||
}
|
}
|
||||||
let ex;
|
let ex;
|
||||||
const why;
|
const why = 2;
|
||||||
class Zed {};
|
class Zed {};
|
||||||
var wut;
|
var wut;
|
||||||
console.log(x, y, Zee);
|
console.log(x, y, Zee);
|
||||||
@@ -90,7 +90,7 @@ remove_unused_in_global_block: {
|
|||||||
expect: {
|
expect: {
|
||||||
var w;
|
var w;
|
||||||
let ex;
|
let ex;
|
||||||
const why;
|
const why = 2;
|
||||||
class Zed {};
|
class Zed {};
|
||||||
var wut;
|
var wut;
|
||||||
console.log(x, y, Zee);
|
console.log(x, y, Zee);
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ issue_1664: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
|
reminify: false // FIXME - block scoped function
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1672_for: {
|
issue_1672_for: {
|
||||||
|
|||||||
@@ -2296,6 +2296,7 @@ toplevel_single_reference: {
|
|||||||
unused_orig: {
|
unused_orig: {
|
||||||
options = {
|
options = {
|
||||||
collapse_vars: true,
|
collapse_vars: true,
|
||||||
|
dead_code: true,
|
||||||
passes: 2,
|
passes: 2,
|
||||||
reduce_funcs: true,
|
reduce_funcs: true,
|
||||||
reduce_vars: true,
|
reduce_vars: true,
|
||||||
@@ -2323,7 +2324,7 @@ unused_orig: {
|
|||||||
var c = b;
|
var c = b;
|
||||||
for (var d in c) {
|
for (var d in c) {
|
||||||
var a;
|
var a;
|
||||||
return --b + (a = c[0]);
|
return --b + c[0];
|
||||||
}
|
}
|
||||||
a && a.NaN;
|
a && a.NaN;
|
||||||
}([2]), a);
|
}([2]), a);
|
||||||
@@ -4313,3 +4314,103 @@ replace_all_var: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cascade_statement: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f1(a, b) {
|
||||||
|
var c;
|
||||||
|
if (a)
|
||||||
|
return c = b, c || a;
|
||||||
|
else
|
||||||
|
c = a, c(b);
|
||||||
|
}
|
||||||
|
function f2(a, b) {
|
||||||
|
var c;
|
||||||
|
while (a)
|
||||||
|
c = b, a = c + b;
|
||||||
|
do
|
||||||
|
throw c = a + b, c;
|
||||||
|
while (c);
|
||||||
|
}
|
||||||
|
function f3(a, b) {
|
||||||
|
for (; a < b; a++)
|
||||||
|
if (c = a, c && b)
|
||||||
|
var c = (c = b(a), c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f1(a, b) {
|
||||||
|
var c;
|
||||||
|
if (a)
|
||||||
|
return (c = b) || a;
|
||||||
|
else
|
||||||
|
(c = a)(b);
|
||||||
|
}
|
||||||
|
function f2(a, b) {
|
||||||
|
var c;
|
||||||
|
while (a)
|
||||||
|
a = (c = b) + b;
|
||||||
|
do
|
||||||
|
throw c = a + b;
|
||||||
|
while (c);
|
||||||
|
}
|
||||||
|
function f3(a, b) {
|
||||||
|
for (; a < b; a++)
|
||||||
|
if ((c = a) && b)
|
||||||
|
var c = c = b(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cascade_forin: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
function f(b) {
|
||||||
|
return [ b, b, b ];
|
||||||
|
}
|
||||||
|
for (var c in a = console, f(a))
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
function f(b) {
|
||||||
|
return [ b, b, b ];
|
||||||
|
}
|
||||||
|
for (var c in f(a = console))
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_builtin: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
pure_getters: "strict",
|
||||||
|
unsafe: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
var b = Math.abs(a);
|
||||||
|
return Math.pow(b, 2);
|
||||||
|
}
|
||||||
|
console.log(f(-1), f(2));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
return Math.pow(Math.abs(a), 2);
|
||||||
|
}
|
||||||
|
console.log(f(-1), f(2));
|
||||||
|
}
|
||||||
|
expect_stdout: "1 4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1224,3 +1224,46 @@ hoist_decl: {
|
|||||||
x() ? y() : z();
|
x() ? y() : z();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
to_and_or: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var values = [
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
"foo",
|
||||||
|
false,
|
||||||
|
-1 / 0,
|
||||||
|
void 0,
|
||||||
|
];
|
||||||
|
values.forEach(function(x) {
|
||||||
|
values.forEach(function(y) {
|
||||||
|
values.forEach(function(z) {
|
||||||
|
console.log(x ? y || z : z);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var values = [
|
||||||
|
0,
|
||||||
|
null,
|
||||||
|
true,
|
||||||
|
"foo",
|
||||||
|
false,
|
||||||
|
-1 / 0,
|
||||||
|
void 0,
|
||||||
|
];
|
||||||
|
values.forEach(function(x) {
|
||||||
|
values.forEach(function(y) {
|
||||||
|
values.forEach(function(z) {
|
||||||
|
console.log(x && y || z);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ dead_code_2_should_warn: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
|
reminify: false // FIXME - block scoped function
|
||||||
}
|
}
|
||||||
|
|
||||||
dead_code_2_should_warn_strict: {
|
dead_code_2_should_warn_strict: {
|
||||||
@@ -100,6 +101,7 @@ dead_code_2_should_warn_strict: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
|
reminify: false // FIXME - block scoped function
|
||||||
}
|
}
|
||||||
|
|
||||||
dead_code_constant_boolean_should_warn_more: {
|
dead_code_constant_boolean_should_warn_more: {
|
||||||
@@ -135,6 +137,7 @@ dead_code_constant_boolean_should_warn_more: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
|
reminify: false // FIXME - block scoped function
|
||||||
}
|
}
|
||||||
|
|
||||||
dead_code_constant_boolean_should_warn_more_strict: {
|
dead_code_constant_boolean_should_warn_more_strict: {
|
||||||
@@ -171,6 +174,7 @@ dead_code_constant_boolean_should_warn_more_strict: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
|
reminify: false // FIXME - block scoped function
|
||||||
}
|
}
|
||||||
|
|
||||||
dead_code_block_decls_die: {
|
dead_code_block_decls_die: {
|
||||||
@@ -1128,3 +1132,49 @@ issue_2701: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "function"
|
expect_stdout: "function"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2749: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 2, c = "PASS";
|
||||||
|
while (a--)
|
||||||
|
(function() {
|
||||||
|
return b ? c = "FAIL" : b = 1;
|
||||||
|
try {
|
||||||
|
} catch (b) {
|
||||||
|
var b;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 2, c = "PASS";
|
||||||
|
while (a--)
|
||||||
|
b = void 0, b ? c = "FAIL" : b = 1;
|
||||||
|
var b;
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe_builtin: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(!w).constructor(x);
|
||||||
|
Math.abs(y);
|
||||||
|
[ 1, 2, z ].valueOf();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
w, x;
|
||||||
|
y;
|
||||||
|
z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ unused_block_decls: {
|
|||||||
input: {
|
input: {
|
||||||
function foo() {
|
function foo() {
|
||||||
{
|
{
|
||||||
const x;
|
const x = 1;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let y;
|
let y;
|
||||||
@@ -2018,3 +2018,78 @@ cascade_drop_assign: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chained_3: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
var c = a, c = b;
|
||||||
|
b++;
|
||||||
|
return c;
|
||||||
|
}(1, 2));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a, b) {
|
||||||
|
var c = b;
|
||||||
|
b++;
|
||||||
|
return c;
|
||||||
|
}(0, 2));
|
||||||
|
}
|
||||||
|
expect_stdout: "2"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2768: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL", c = 1;
|
||||||
|
var c = function(b) {
|
||||||
|
var d = b = a;
|
||||||
|
var e = --b + (d && (a = "PASS"));
|
||||||
|
}();
|
||||||
|
console.log(a, typeof c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
var c = (d = a, 0, void (d && (a = "PASS")));
|
||||||
|
var d;
|
||||||
|
console.log(a, typeof c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2846: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
var a = 0;
|
||||||
|
b && b(a);
|
||||||
|
return a++;
|
||||||
|
}
|
||||||
|
var c = f();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var c = function(a, b) {
|
||||||
|
a = 0;
|
||||||
|
b && b(a);
|
||||||
|
return a++;
|
||||||
|
}();
|
||||||
|
console.log(c);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1287,6 +1287,9 @@ issue_2231_1: {
|
|||||||
console.log(Object.keys(void 0));
|
console.log(Object.keys(void 0));
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Error evaluating Object.keys(void 0) [test/compress/evaluate.js:1284,20]",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_2231_2: {
|
issue_2231_2: {
|
||||||
@@ -1301,6 +1304,23 @@ issue_2231_2: {
|
|||||||
console.log(Object.getOwnPropertyNames(null));
|
console.log(Object.getOwnPropertyNames(null));
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
|
expect_warnings: [
|
||||||
|
"WARN: Error evaluating Object.getOwnPropertyNames(null) [test/compress/evaluate.js:1301,20]",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2231_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(Object.keys({ foo: "bar" })[0]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("foo");
|
||||||
|
}
|
||||||
|
expect_stdout: "foo"
|
||||||
}
|
}
|
||||||
|
|
||||||
self_comparison_1: {
|
self_comparison_1: {
|
||||||
@@ -1423,13 +1443,27 @@ issue_2535_3: {
|
|||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
expect_warnings: [
|
expect_warnings: [
|
||||||
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1409,20]",
|
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1429,20]",
|
||||||
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1410,20]",
|
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1430,20]",
|
||||||
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1411,20]",
|
"WARN: Dropping side-effect-free && [test/compress/evaluate.js:1431,20]",
|
||||||
"WARN: Condition left of && always false [test/compress/evaluate.js:1411,20]",
|
"WARN: Condition left of && always false [test/compress/evaluate.js:1431,20]",
|
||||||
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1412,20]",
|
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1432,20]",
|
||||||
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1413,20]",
|
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1433,20]",
|
||||||
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1414,20]",
|
"WARN: Dropping side-effect-free || [test/compress/evaluate.js:1434,20]",
|
||||||
"WARN: Condition left of || always true [test/compress/evaluate.js:1414,20]",
|
"WARN: Condition left of || always true [test/compress/evaluate.js:1434,20]",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2822: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log([ function() {}, "PASS", "FAIL" ][1]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ issue_203: {
|
|||||||
options = {
|
options = {
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
unsafe_Func: true,
|
unsafe_Function: true,
|
||||||
unused: true,
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
@@ -2117,3 +2117,41 @@ issue_2737_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2783: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
return g;
|
||||||
|
function f(a) {
|
||||||
|
var b = a.b;
|
||||||
|
if (b) return b;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
function g(o, i) {
|
||||||
|
while (i--) {
|
||||||
|
console.log(f(o));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})()({ b: "PASS" }, 1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
return function(o,i) {
|
||||||
|
while (i--) console.log(f(o));
|
||||||
|
};
|
||||||
|
function f(a) {
|
||||||
|
var b = a.b;
|
||||||
|
return b || a;
|
||||||
|
}
|
||||||
|
})()({ b: "PASS" },1);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1212,3 +1212,230 @@ issue_2676: {
|
|||||||
(class {}).a = 42;
|
(class {}).a = 42;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2762: {
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var bar = 1, T = true;
|
||||||
|
(function() {
|
||||||
|
if (T) {
|
||||||
|
const a = function() {
|
||||||
|
var foo = bar;
|
||||||
|
console.log(foo, a.prop, b.prop);
|
||||||
|
};
|
||||||
|
a.prop = 2;
|
||||||
|
const b = { prop: 3 };
|
||||||
|
a();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var bar = 1, T = true;
|
||||||
|
(function() {
|
||||||
|
if (T) {
|
||||||
|
const o = function() {
|
||||||
|
var p = bar;
|
||||||
|
console.log(p, o.prop, r.prop);
|
||||||
|
};
|
||||||
|
o.prop = 2;
|
||||||
|
const r = { prop: 3 };
|
||||||
|
o();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "1 2 3"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2794_1: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 1,
|
||||||
|
properties: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: false,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo() {
|
||||||
|
for (const a of func(value)) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
function func(va) {
|
||||||
|
return doSomething(va);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function doSomething(x) {
|
||||||
|
return [ x, 2 * x, 3 * x ];
|
||||||
|
}
|
||||||
|
const value = 10;
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo() {
|
||||||
|
for (const a of doSomething(value)) console.log(a);
|
||||||
|
}
|
||||||
|
function doSomething(x) {
|
||||||
|
return [ x, 2 * x, 3 * x ];
|
||||||
|
}
|
||||||
|
const value = 10;
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"10",
|
||||||
|
"20",
|
||||||
|
"30",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2794_2: {
|
||||||
|
mangle = {
|
||||||
|
toplevel: false,
|
||||||
|
}
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 1,
|
||||||
|
properties: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: false,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo() {
|
||||||
|
for (const a of func(value)) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
function func(va) {
|
||||||
|
return doSomething(va);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function doSomething(x) {
|
||||||
|
return [ x, 2 * x, 3 * x ];
|
||||||
|
}
|
||||||
|
const value = 10;
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function foo() {
|
||||||
|
for (const o of doSomething(value)) console.log(o);
|
||||||
|
}
|
||||||
|
function doSomething(o) {
|
||||||
|
return [ o, 2 * o, 3 * o ];
|
||||||
|
}
|
||||||
|
const value = 10;
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"10",
|
||||||
|
"20",
|
||||||
|
"30",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2794_3: {
|
||||||
|
mangle = {
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: 3,
|
||||||
|
passes: 3,
|
||||||
|
properties: true,
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function foo() {
|
||||||
|
for (const a of func(value)) {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
function func(va) {
|
||||||
|
return doSomething(va);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function doSomething(x) {
|
||||||
|
return [ x, 2 * x, 3 * x ];
|
||||||
|
}
|
||||||
|
const value = 10;
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
for (const o of [ 10, 20, 30 ]) console.log(o);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"10",
|
||||||
|
"20",
|
||||||
|
"30",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2794_4: {
|
||||||
|
options = {}
|
||||||
|
input: {
|
||||||
|
for (var x of ([1, 2], [3, 4])) {
|
||||||
|
console.log(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "for(var x of([1,2],[3,4]))console.log(x);"
|
||||||
|
expect_stdout: [
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2794_5: {
|
||||||
|
mangle = {}
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
passes: 1,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var x of ([1, 2], [3, 4])) {
|
||||||
|
console.log(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "for(var x of[3,4])console.log(x);"
|
||||||
|
expect_stdout: [
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2794_6: {
|
||||||
|
options = {
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
// TODO (or not): have parser flag invalid for-of expression.
|
||||||
|
// Consider it an uglify extension in the meantime.
|
||||||
|
for (let e of [1,2], [3,4,5]) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_exact: "for(let e of([1,2],[3,4,5]))console.log(e);"
|
||||||
|
expect_stdout: [
|
||||||
|
"3",
|
||||||
|
"4",
|
||||||
|
"5",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
@@ -897,3 +897,25 @@ toplevel_var: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "3"
|
expect_stdout: "3"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
undefined_key: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
hoist_props: true,
|
||||||
|
join_vars: true,
|
||||||
|
passes: 4,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a, o = {};
|
||||||
|
o[a] = 1;
|
||||||
|
o.b = 2;
|
||||||
|
console.log(o[a] + o.b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(3);
|
||||||
|
}
|
||||||
|
expect_stdout: "3"
|
||||||
|
}
|
||||||
|
|||||||
@@ -454,3 +454,39 @@ if_if_return_return: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2747: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
if_return: true,
|
||||||
|
sequences: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
function f(baz) {
|
||||||
|
if (baz === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let r;
|
||||||
|
if (baz > 2) {
|
||||||
|
r = 4;
|
||||||
|
} else {
|
||||||
|
r = 5;
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1), f(3));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
function f(baz) {
|
||||||
|
if (0 === baz) return null;
|
||||||
|
let r;
|
||||||
|
return r = baz > 2 ? 4 : 5, r;
|
||||||
|
}
|
||||||
|
console.log(f(0), f(1), f(3));
|
||||||
|
}
|
||||||
|
expect_stdout: "null 5 4"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ unsafe_undefined: {
|
|||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
unsafe: true
|
unsafe_undefined: true,
|
||||||
}
|
}
|
||||||
mangle = {}
|
mangle = {}
|
||||||
input: {
|
input: {
|
||||||
@@ -30,7 +30,7 @@ keep_fnames: {
|
|||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
unsafe: true
|
unsafe_undefined: true,
|
||||||
}
|
}
|
||||||
mangle = {
|
mangle = {
|
||||||
keep_fnames: true
|
keep_fnames: true
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ same_variable_in_multiple_for_loop: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
same_variable_in_multiple_forOf: {
|
same_variable_in_multiple_forOf: {
|
||||||
@@ -79,6 +80,7 @@ same_variable_in_multiple_forOf: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
same_variable_in_multiple_forIn: {
|
same_variable_in_multiple_forIn: {
|
||||||
@@ -120,6 +122,7 @@ same_variable_in_multiple_forIn: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
different_variable_in_multiple_for_loop: {
|
different_variable_in_multiple_for_loop: {
|
||||||
@@ -162,6 +165,7 @@ different_variable_in_multiple_for_loop: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
different_variable_in_multiple_forOf: {
|
different_variable_in_multiple_forOf: {
|
||||||
@@ -203,6 +207,7 @@ different_variable_in_multiple_forOf: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
different_variable_in_multiple_forIn: {
|
different_variable_in_multiple_forIn: {
|
||||||
@@ -244,6 +249,175 @@ different_variable_in_multiple_forIn: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
same_variable_in_multiple_forOf_sequences_let: {
|
||||||
|
options = {
|
||||||
|
hoist_funs: true,
|
||||||
|
dead_code: true,
|
||||||
|
conditionals: true,
|
||||||
|
comparisons: true,
|
||||||
|
evaluate: true,
|
||||||
|
booleans: true,
|
||||||
|
loops: true,
|
||||||
|
unused: true,
|
||||||
|
keep_fargs: true,
|
||||||
|
if_return: true,
|
||||||
|
join_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var test = [ "a", "b", "c" ];
|
||||||
|
for (let tmp of test) {
|
||||||
|
console.log(tmp);
|
||||||
|
let dd;
|
||||||
|
dd = [ "e", "f", "g" ];
|
||||||
|
for (let tmp of dd) {
|
||||||
|
console.log(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var test = [ "a", "b", "c" ];
|
||||||
|
for (let o of test) {
|
||||||
|
let e;
|
||||||
|
console.log(o), e = [ "e", "f", "g" ];
|
||||||
|
for (let o of e)
|
||||||
|
console.log(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
same_variable_in_multiple_forOf_sequences_const: {
|
||||||
|
options = {
|
||||||
|
hoist_funs: true,
|
||||||
|
dead_code: true,
|
||||||
|
conditionals: true,
|
||||||
|
comparisons: true,
|
||||||
|
evaluate: true,
|
||||||
|
booleans: true,
|
||||||
|
loops: true,
|
||||||
|
unused: true,
|
||||||
|
keep_fargs: true,
|
||||||
|
if_return: true,
|
||||||
|
join_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var test = [ "a", "b", "c" ];
|
||||||
|
for (const tmp of test) {
|
||||||
|
console.log(tmp);
|
||||||
|
let dd;
|
||||||
|
dd = [ "e", "f", "g" ];
|
||||||
|
for (const tmp of dd) {
|
||||||
|
console.log(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var test = [ "a", "b", "c" ];
|
||||||
|
for (const o of test) {
|
||||||
|
let t;
|
||||||
|
console.log(o), t = [ "e", "f", "g" ];
|
||||||
|
for (const o of t)
|
||||||
|
console.log(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
same_variable_in_multiple_forIn_sequences_let: {
|
||||||
|
options = {
|
||||||
|
hoist_funs: true,
|
||||||
|
dead_code: true,
|
||||||
|
conditionals: true,
|
||||||
|
comparisons: true,
|
||||||
|
evaluate: true,
|
||||||
|
booleans: true,
|
||||||
|
loops: true,
|
||||||
|
unused: false,
|
||||||
|
keep_fargs: true,
|
||||||
|
if_return: true,
|
||||||
|
join_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var test = [ "a", "b", "c" ];
|
||||||
|
for (let tmp in test) {
|
||||||
|
console.log(tmp);
|
||||||
|
let dd;
|
||||||
|
dd = [ "e", "f", "g" ];
|
||||||
|
for (let tmp in test) {
|
||||||
|
console.log(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var test = [ "a", "b", "c" ];
|
||||||
|
for (let e in test) {
|
||||||
|
let t;
|
||||||
|
console.log(e), t = [ "e", "f", "g" ];
|
||||||
|
for (let e in test)
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
same_variable_in_multiple_forIn_sequences_const: {
|
||||||
|
options = {
|
||||||
|
hoist_funs: true,
|
||||||
|
dead_code: true,
|
||||||
|
conditionals: true,
|
||||||
|
comparisons: true,
|
||||||
|
evaluate: true,
|
||||||
|
booleans: true,
|
||||||
|
loops: true,
|
||||||
|
unused: false,
|
||||||
|
keep_fargs: true,
|
||||||
|
if_return: true,
|
||||||
|
join_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
collapse_vars: true,
|
||||||
|
}
|
||||||
|
mangle = {}
|
||||||
|
input: {
|
||||||
|
var test = [ "a", "b", "c" ];
|
||||||
|
for (const tmp in test) {
|
||||||
|
console.log(tmp);
|
||||||
|
let dd;
|
||||||
|
dd = [ "e", "f", "g" ];
|
||||||
|
for (const tmp in test) {
|
||||||
|
console.log(tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var test = [ "a", "b", "c" ];
|
||||||
|
for (const o in test) {
|
||||||
|
let t;
|
||||||
|
console.log(o), t = [ "e", "f", "g" ];
|
||||||
|
for (const o in test)
|
||||||
|
console.log(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
more_variable_in_multiple_for: {
|
more_variable_in_multiple_for: {
|
||||||
@@ -281,4 +455,5 @@ more_variable_in_multiple_for: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect_stdout: true
|
expect_stdout: true
|
||||||
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ unsafe_undefined: {
|
|||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
if_return: true,
|
if_return: true,
|
||||||
unsafe: true,
|
unsafe_undefined: true,
|
||||||
}
|
}
|
||||||
mangle = {}
|
mangle = {}
|
||||||
input: {
|
input: {
|
||||||
|
|||||||
@@ -84,12 +84,12 @@ numeric_literal: {
|
|||||||
' 0: 0,',
|
' 0: 0,',
|
||||||
' "-0": 1,',
|
' "-0": 1,',
|
||||||
' 42: 2,',
|
' 42: 2,',
|
||||||
' "42": 3,',
|
' 42: 3,',
|
||||||
' 37: 4,',
|
' 37: 4,',
|
||||||
' o: 5,',
|
' o: 5,',
|
||||||
' 1e42: 6,',
|
' 1e42: 6,',
|
||||||
' b: 7,',
|
' b: 7,',
|
||||||
' "1e+42": 8',
|
' 1e42: 8',
|
||||||
'};',
|
'};',
|
||||||
'',
|
'',
|
||||||
'console.log(obj[-0], obj[-""], obj["-0"]);',
|
'console.log(obj[-0], obj[-""], obj["-0"]);',
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
compress_new_function: {
|
compress_new_function: {
|
||||||
options = {
|
options = {
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
unsafe_Func: true,
|
unsafe_Function: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
new Function("aa, bb", 'return aa;');
|
new Function("aa, bb", 'return aa;');
|
||||||
@@ -15,7 +15,7 @@ compress_new_function: {
|
|||||||
compress_new_function_with_destruct: {
|
compress_new_function_with_destruct: {
|
||||||
options = {
|
options = {
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
unsafe_Func: true,
|
unsafe_Function: true,
|
||||||
ecma: 6
|
ecma: 6
|
||||||
}
|
}
|
||||||
beautify = {
|
beautify = {
|
||||||
@@ -38,7 +38,7 @@ compress_new_function_with_destruct_arrows: {
|
|||||||
arrows: true,
|
arrows: true,
|
||||||
unsafe_arrows: true,
|
unsafe_arrows: true,
|
||||||
unsafe: true,
|
unsafe: true,
|
||||||
unsafe_Func: true,
|
unsafe_Function: true,
|
||||||
ecma: 6,
|
ecma: 6,
|
||||||
}
|
}
|
||||||
beautify = {
|
beautify = {
|
||||||
|
|||||||
@@ -536,3 +536,182 @@ dead_code_condition: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2740_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (; ; ) break;
|
||||||
|
for (a(); ; ) break;
|
||||||
|
for (; b(); ) break;
|
||||||
|
for (c(); d(); ) break;
|
||||||
|
for (; ; e()) break;
|
||||||
|
for (f(); ; g()) break;
|
||||||
|
for (; h(); i()) break;
|
||||||
|
for (j(); k(); l()) break;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a();
|
||||||
|
b();
|
||||||
|
c();
|
||||||
|
d();
|
||||||
|
f();
|
||||||
|
h();
|
||||||
|
j();
|
||||||
|
k();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2740_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
passes: 2,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L1: while (x()) {
|
||||||
|
break L1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
x();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2740_3: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L1: for (var x = 0; x < 3; x++) {
|
||||||
|
L2: for (var y = 0; y < 2; y++) {
|
||||||
|
break L1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(x, y);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
L1: for (var x = 0; x < 3; x++)
|
||||||
|
for (var y = 0; y < 2; y++)
|
||||||
|
break L1;
|
||||||
|
console.log(x, y);
|
||||||
|
}
|
||||||
|
expect_stdout: "0 0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2740_4: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
passes: 2,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L1: for (var x = 0; x < 3; x++) {
|
||||||
|
L2: for (var y = 0; y < 2; y++) {
|
||||||
|
break L2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(x, y);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var x = 0; x < 3; x++) {
|
||||||
|
var y = 0;
|
||||||
|
y < 2;
|
||||||
|
}
|
||||||
|
console.log(x, y);
|
||||||
|
}
|
||||||
|
expect_stdout: "3 0"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2740_5: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
passes: 2,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
L1: for (var x = 0; x < 3; x++) {
|
||||||
|
break L1;
|
||||||
|
L2: for (var y = 0; y < 2; y++) {
|
||||||
|
break L2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(x, y);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var x = 0;
|
||||||
|
x < 3;
|
||||||
|
var y;
|
||||||
|
console.log(x,y);
|
||||||
|
}
|
||||||
|
expect_stdout: "0 undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2740_6: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
const a = 9, b = 0;
|
||||||
|
for (const a = 1; a < 3; ++b) break;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
const a = 9, b = 0;
|
||||||
|
{
|
||||||
|
const a = 1;
|
||||||
|
a < 3;
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "9 0"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2740_7: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
let a = 9, b = 0;
|
||||||
|
for (const a = 1; a < 3; ++b) break;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
let a = 9, b = 0;
|
||||||
|
{
|
||||||
|
const a = 1;
|
||||||
|
a < 3;
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "9 0"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2740_8: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
loops: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 9, b = 0;
|
||||||
|
for (const a = 1; a < 3; ++b) break;
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 9, b = 0;
|
||||||
|
{
|
||||||
|
const a = 1;
|
||||||
|
a < 3;
|
||||||
|
}
|
||||||
|
console.log(a, b);
|
||||||
|
}
|
||||||
|
expect_stdout: "9 0"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
@@ -585,6 +585,25 @@ native_prototype: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
native_prototype_lhs: {
|
||||||
|
options = {
|
||||||
|
unsafe_proto: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
Function.prototype.bar = "PASS";
|
||||||
|
return function() {};
|
||||||
|
}().bar);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
Function.prototype.bar = "PASS";
|
||||||
|
return function() {};
|
||||||
|
}().bar);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
accessor_boolean: {
|
accessor_boolean: {
|
||||||
input: {
|
input: {
|
||||||
var a = 1;
|
var a = 1;
|
||||||
@@ -1377,3 +1396,501 @@ const_prop_assign_pure: {
|
|||||||
x();
|
x();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
join_object_assignments_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var x = {
|
||||||
|
a: 1,
|
||||||
|
c: (console.log("c"), "C"),
|
||||||
|
};
|
||||||
|
x.b = 2;
|
||||||
|
x[3] = function() {
|
||||||
|
console.log(x);
|
||||||
|
},
|
||||||
|
x["a"] = /foo/,
|
||||||
|
x.bar = x;
|
||||||
|
return x;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var x = {
|
||||||
|
a: 1,
|
||||||
|
c: (console.log("c"), "C"),
|
||||||
|
b: 2,
|
||||||
|
3: function() {
|
||||||
|
console.log(x);
|
||||||
|
},
|
||||||
|
a: /foo/,
|
||||||
|
};
|
||||||
|
x.bar = x;
|
||||||
|
return x;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: true
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
hoist_props: true,
|
||||||
|
join_vars: true,
|
||||||
|
passes: 3,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {
|
||||||
|
foo: 1,
|
||||||
|
};
|
||||||
|
o.bar = 2;
|
||||||
|
o.baz = 3;
|
||||||
|
console.log(o.foo, o.bar + o.bar, o.foo * o.bar * o.baz);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(1, 4, 6);
|
||||||
|
}
|
||||||
|
expect_stdout: "1 4 6"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_3: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = {
|
||||||
|
a: "PASS",
|
||||||
|
}, a = o.a;
|
||||||
|
o.a = "FAIL";
|
||||||
|
return a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = {
|
||||||
|
a: "PASS",
|
||||||
|
}, a = o.a;
|
||||||
|
o.a = "FAIL";
|
||||||
|
return a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_return_1: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = {
|
||||||
|
p: 3
|
||||||
|
};
|
||||||
|
return o.q = "foo";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = {
|
||||||
|
p: 3,
|
||||||
|
q: "foo"
|
||||||
|
};
|
||||||
|
return o.q;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "foo"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_return_2: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = {
|
||||||
|
p: 3
|
||||||
|
};
|
||||||
|
return o.q = /foo/,
|
||||||
|
o.r = "bar";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = {
|
||||||
|
p: 3,
|
||||||
|
q: /foo/,
|
||||||
|
r: "bar"
|
||||||
|
};
|
||||||
|
return o.r;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "bar"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_return_3: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = {
|
||||||
|
p: 3
|
||||||
|
};
|
||||||
|
return o.q = "foo",
|
||||||
|
o.p += "",
|
||||||
|
console.log(o.q),
|
||||||
|
o.p;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = {
|
||||||
|
p: 3,
|
||||||
|
q: "foo"
|
||||||
|
};
|
||||||
|
return o.p += "",
|
||||||
|
console.log(o.q),
|
||||||
|
o.p;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"3",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_for: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = {
|
||||||
|
p: 3
|
||||||
|
};
|
||||||
|
for (o.q = "foo"; console.log(o.q););
|
||||||
|
return o.p;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
for (var o = {
|
||||||
|
p: 3,
|
||||||
|
q: "foo"
|
||||||
|
}; console.log(o.q););
|
||||||
|
return o.p;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"3",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_if: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = {};
|
||||||
|
if (o.a = "PASS") return o.a;
|
||||||
|
}())
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = { a: "PASS" };
|
||||||
|
if (o.a) return o.a;
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_forin: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = {};
|
||||||
|
for (var a in o.a = "PASS", o)
|
||||||
|
return o[a];
|
||||||
|
}())
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var o = { a: "PASS" };
|
||||||
|
for (var a in o)
|
||||||
|
return o[a];
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_negative: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
o[0] = 0;
|
||||||
|
o[-0] = 1;
|
||||||
|
o[-1] = 2;
|
||||||
|
console.log(o[0], o[-0], o[-1]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
0: 0,
|
||||||
|
0: 1,
|
||||||
|
"-1": 2
|
||||||
|
};
|
||||||
|
console.log(o[0], o[-0], o[-1]);
|
||||||
|
}
|
||||||
|
expect_stdout: "1 1 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_NaN_1: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
o[NaN] = 1;
|
||||||
|
o[0/0] = 2;
|
||||||
|
console.log(o[NaN], o[NaN]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {};
|
||||||
|
o[NaN] = 1;
|
||||||
|
o[0/0] = 2;
|
||||||
|
console.log(o[NaN], o[NaN]);
|
||||||
|
}
|
||||||
|
expect_stdout: "2 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_NaN_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
o[NaN] = 1;
|
||||||
|
o[0/0] = 2;
|
||||||
|
console.log(o[NaN], o[NaN]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
NaN: 1,
|
||||||
|
NaN: 2
|
||||||
|
};
|
||||||
|
console.log(o.NaN, o.NaN);
|
||||||
|
}
|
||||||
|
expect_stdout: "2 2"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_null_0: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
o[null] = 1;
|
||||||
|
console.log(o[null]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {};
|
||||||
|
o[null] = 1;
|
||||||
|
console.log(o[null]);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_null_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
o[null] = 1;
|
||||||
|
console.log(o[null]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
null: 1
|
||||||
|
};
|
||||||
|
console.log(o.null);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_void_0: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
o[void 0] = 1;
|
||||||
|
console.log(o[void 0]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
undefined: 1
|
||||||
|
};
|
||||||
|
console.log(o[void 0]);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_undefined_1: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
o[undefined] = 1;
|
||||||
|
console.log(o[undefined]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {};
|
||||||
|
o[void 0] = 1;
|
||||||
|
console.log(o[void 0]);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_undefined_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
o[undefined] = 1;
|
||||||
|
console.log(o[undefined]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
undefined : 1
|
||||||
|
};
|
||||||
|
console.log(o[void 0]);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_Infinity: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
o[Infinity] = 1;
|
||||||
|
o[1/0] = 2;
|
||||||
|
o[-Infinity] = 3;
|
||||||
|
o[-1/0] = 4;
|
||||||
|
console.log(o[Infinity], o[1/0], o[-Infinity], o[-1/0]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
Infinity: 1,
|
||||||
|
Infinity: 2,
|
||||||
|
"-Infinity": 3,
|
||||||
|
"-Infinity": 4
|
||||||
|
};
|
||||||
|
console.log(o[1/0], o[1/0], o[-1/0], o[-1/0]);
|
||||||
|
}
|
||||||
|
expect_stdout: "2 2 4 4"
|
||||||
|
}
|
||||||
|
|
||||||
|
join_object_assignments_regex: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
join_vars: true,
|
||||||
|
properties: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = {};
|
||||||
|
o[/rx/] = 1;
|
||||||
|
console.log(o[/rx/]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = {
|
||||||
|
"/rx/": 1
|
||||||
|
};
|
||||||
|
console.log(o[/rx/]);
|
||||||
|
}
|
||||||
|
expect_stdout: "1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2816: {
|
||||||
|
options = {
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var o = {
|
||||||
|
a: 1
|
||||||
|
};
|
||||||
|
o.b = 2;
|
||||||
|
o.a = 3;
|
||||||
|
o.c = 4;
|
||||||
|
console.log(o.a, o.b, o.c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var o = {
|
||||||
|
a: 1,
|
||||||
|
b: 2
|
||||||
|
};
|
||||||
|
o.a = 3;
|
||||||
|
o.c = 4;
|
||||||
|
console.log(o.a, o.b, o.c);
|
||||||
|
}
|
||||||
|
expect_stdout: "3 2 4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2816_ecma6: {
|
||||||
|
options = {
|
||||||
|
ecma: "6",
|
||||||
|
join_vars: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var o = {
|
||||||
|
a: 1
|
||||||
|
};
|
||||||
|
o.b = 2;
|
||||||
|
o.a = 3;
|
||||||
|
o.c = 4;
|
||||||
|
console.log(o.a, o.b, o.c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var o = {
|
||||||
|
a: 1,
|
||||||
|
b: 2,
|
||||||
|
a: 3,
|
||||||
|
c: 4
|
||||||
|
};
|
||||||
|
console.log(o.a, o.b, o.c);
|
||||||
|
}
|
||||||
|
expect_stdout: "3 2 4"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -818,3 +818,30 @@ issue_2678: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2838: {
|
||||||
|
options = {
|
||||||
|
pure_getters: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
(a || b).c = "PASS";
|
||||||
|
(function() {
|
||||||
|
return f(a, b);
|
||||||
|
}).prototype.foo = "bar";
|
||||||
|
}
|
||||||
|
var o = {};
|
||||||
|
f(null, o);
|
||||||
|
console.log(o.c);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
(a || b).c = "PASS";
|
||||||
|
}
|
||||||
|
var o = {};
|
||||||
|
f(null, o);
|
||||||
|
console.log(o.c);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -5809,3 +5809,167 @@ duplicate_lambda_defun_name_2: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "0"
|
expect_stdout: "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2757_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
let u;
|
||||||
|
(function() {
|
||||||
|
let v;
|
||||||
|
console.log(u, v);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
let u;
|
||||||
|
console.log(u, void 0);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined undefined"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2757_2: {
|
||||||
|
options = {
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
let bar;
|
||||||
|
const unused = function() {
|
||||||
|
bar = true;
|
||||||
|
};
|
||||||
|
if (!bar) {
|
||||||
|
console.log(1);
|
||||||
|
}
|
||||||
|
console.log(2);
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(1),
|
||||||
|
console.log(2);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
]
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2774: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log({
|
||||||
|
get a() {
|
||||||
|
var b;
|
||||||
|
(b = true) && b.c;
|
||||||
|
b = void 0;
|
||||||
|
}
|
||||||
|
}.a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log({
|
||||||
|
get a() {
|
||||||
|
var b;
|
||||||
|
(b = true) && b.c;
|
||||||
|
b = void 0;
|
||||||
|
}
|
||||||
|
}.a);
|
||||||
|
}
|
||||||
|
expect_stdout: "undefined"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2799_1: {
|
||||||
|
options = {
|
||||||
|
reduce_funcs: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
return f;
|
||||||
|
function f(n) {
|
||||||
|
function g(i) {
|
||||||
|
return i && i + g(i - 1);
|
||||||
|
}
|
||||||
|
function h(j) {
|
||||||
|
return g(j);
|
||||||
|
}
|
||||||
|
return h(n);
|
||||||
|
}
|
||||||
|
}()(5));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
return function(n) {
|
||||||
|
return function(j) {
|
||||||
|
return function g(i) {
|
||||||
|
return i && i + g(i - 1);
|
||||||
|
}(j);
|
||||||
|
}(n);
|
||||||
|
}
|
||||||
|
}()(5));
|
||||||
|
}
|
||||||
|
expect_stdout: "15"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2799_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
unsafe_proto: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
function foo() {
|
||||||
|
Function.prototype.call.apply(console.log, [ null, "PASS" ]);
|
||||||
|
}
|
||||||
|
foo();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
(function() {
|
||||||
|
(function() {}).call.apply(console.log, [ null, "PASS" ]);
|
||||||
|
})();
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_2836: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
|
console.log(f());
|
||||||
|
function f() {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
return "PASS";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ unsafe_undefined: {
|
|||||||
if_return: true,
|
if_return: true,
|
||||||
sequences: true,
|
sequences: true,
|
||||||
side_effects: true,
|
side_effects: true,
|
||||||
unsafe: true,
|
unsafe_undefined: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
function f(undefined) {
|
function f(undefined) {
|
||||||
@@ -883,3 +883,21 @@ for_init_var: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
forin: {
|
||||||
|
options = {
|
||||||
|
sequences: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var o = [];
|
||||||
|
o.push("PASS");
|
||||||
|
for (var a in o)
|
||||||
|
console.log(o[a]);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var o = [];
|
||||||
|
for (var a in o.push("PASS"), o)
|
||||||
|
console.log(o[a]);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -211,3 +211,43 @@ issue_2689: {
|
|||||||
}
|
}
|
||||||
expect_exact: "function*y(){return new(yield x())}"
|
expect_exact: "function*y(){return new(yield x())}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_2832: {
|
||||||
|
beautify = {
|
||||||
|
beautify: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function* gen(i) {
|
||||||
|
const result = yield (x = i, -x);
|
||||||
|
var x;
|
||||||
|
console.log(x);
|
||||||
|
console.log(result);
|
||||||
|
yield 2;
|
||||||
|
}
|
||||||
|
var x = gen(1);
|
||||||
|
console.log(x.next("first").value);
|
||||||
|
console.log(x.next("second").value);
|
||||||
|
}
|
||||||
|
expect_exact: [
|
||||||
|
"function* gen(i) {",
|
||||||
|
" const result = yield (x = i, -x);",
|
||||||
|
" var x;",
|
||||||
|
" console.log(x);",
|
||||||
|
" console.log(result);",
|
||||||
|
" yield 2;",
|
||||||
|
"}",
|
||||||
|
"",
|
||||||
|
"var x = gen(1);",
|
||||||
|
"",
|
||||||
|
'console.log(x.next("first").value);',
|
||||||
|
"",
|
||||||
|
'console.log(x.next("second").value);',
|
||||||
|
]
|
||||||
|
expect_stdout: [
|
||||||
|
"-1",
|
||||||
|
"1",
|
||||||
|
"second",
|
||||||
|
"2",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,3 @@
|
|||||||
function f() {
|
function f() {
|
||||||
const a;
|
const a;
|
||||||
}
|
}
|
||||||
|
|
||||||
function g() {
|
|
||||||
"use strict";
|
|
||||||
const a;
|
|
||||||
}
|
|
||||||
|
|||||||
6
test/input/rename/input.js
Normal file
6
test/input/rename/input.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
function f(x) {
|
||||||
|
return g(x);
|
||||||
|
function g(x) {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,29 +1,24 @@
|
|||||||
var Mocha = require('mocha'),
|
var fs = require("fs");
|
||||||
fs = require('fs'),
|
var Mocha = require("mocha");
|
||||||
path = require('path');
|
var path = require("path");
|
||||||
|
|
||||||
// Instantiate a Mocha instance.
|
// Instantiate a Mocha instance
|
||||||
var mocha = new Mocha({});
|
var mocha = new Mocha({
|
||||||
|
timeout: 5000
|
||||||
|
});
|
||||||
|
var testDir = __dirname + "/mocha/";
|
||||||
|
|
||||||
var testDir = __dirname + '/mocha/';
|
// Add each .js file to the Mocha instance
|
||||||
|
fs.readdirSync(testDir).filter(function(file) {
|
||||||
// Add each .js file to the mocha instance
|
return /\.js$/.test(file);
|
||||||
fs.readdirSync(testDir).filter(function(file){
|
}).forEach(function(file) {
|
||||||
// Only keep the .js files
|
mocha.addFile(path.join(testDir, file));
|
||||||
return file.substr(-3) === '.js';
|
|
||||||
|
|
||||||
}).forEach(function(file){
|
|
||||||
mocha.addFile(
|
|
||||||
path.join(testDir, file)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = function() {
|
module.exports = function() {
|
||||||
mocha.run(function(failures) {
|
mocha.run(function(failures) {
|
||||||
if (failures !== 0) {
|
if (failures) process.on("exit", function() {
|
||||||
process.on('exit', function () {
|
process.exit(failures);
|
||||||
process.exit(failures);
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -408,7 +408,7 @@ describe("bin/uglifyjs", function () {
|
|||||||
assert.ok(err);
|
assert.ok(err);
|
||||||
assert.strictEqual(stdout, "");
|
assert.strictEqual(stdout, "");
|
||||||
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
assert.strictEqual(stderr.split(/\n/).slice(0, 4).join("\n"), [
|
||||||
"Parse error at test/input/invalid/const.js:7,11",
|
"Parse error at test/input/invalid/const.js:2,11",
|
||||||
" const a;",
|
" const a;",
|
||||||
" ^",
|
" ^",
|
||||||
"ERROR: Missing initializer in const declaration"
|
"ERROR: Missing initializer in const declaration"
|
||||||
|
|||||||
@@ -404,4 +404,19 @@ describe("minify", function() {
|
|||||||
assert.strictEqual(stat.print_to_string(), "a=x()");
|
assert.strictEqual(stat.print_to_string(), "a=x()");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// rename is disabled on harmony due to expand_names bug in for-of loops
|
||||||
|
if (0) describe("rename", function() {
|
||||||
|
it("Should be repeatable", function() {
|
||||||
|
var code = "!function(x){return x(x)}(y);";
|
||||||
|
for (var i = 0; i < 2; i++) {
|
||||||
|
assert.strictEqual(Uglify.minify(code, {
|
||||||
|
compress: {
|
||||||
|
toplevel: true,
|
||||||
|
},
|
||||||
|
rename: true,
|
||||||
|
}).code, "var a;(a=y)(a);");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -208,6 +208,9 @@ function run_compress_tests() {
|
|||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (test.reminify && !reminify(test.options, input_code, input_formatted, test.expect_stdout)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -261,6 +264,16 @@ function parse_test(file) {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function read_boolean(stat) {
|
||||||
|
if (stat.TYPE == "SimpleStatement") {
|
||||||
|
var body = stat.body;
|
||||||
|
if (body instanceof U.AST_Boolean) {
|
||||||
|
return body.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error("Should be boolean");
|
||||||
|
}
|
||||||
|
|
||||||
function read_string(stat) {
|
function read_string(stat) {
|
||||||
if (stat.TYPE == "SimpleStatement") {
|
if (stat.TYPE == "SimpleStatement") {
|
||||||
var body = stat.body;
|
var body = stat.body;
|
||||||
@@ -279,7 +292,11 @@ function parse_test(file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function get_one_test(name, block) {
|
function get_one_test(name, block) {
|
||||||
var test = { name: name, options: {} };
|
var test = {
|
||||||
|
name: name,
|
||||||
|
options: {},
|
||||||
|
reminify: true,
|
||||||
|
};
|
||||||
var tw = new U.TreeWalker(function(node, descend){
|
var tw = new U.TreeWalker(function(node, descend){
|
||||||
if (node instanceof U.AST_Assign) {
|
if (node instanceof U.AST_Assign) {
|
||||||
if (!(node.left instanceof U.AST_SymbolRef)) {
|
if (!(node.left instanceof U.AST_SymbolRef)) {
|
||||||
@@ -299,6 +316,7 @@ function parse_test(file) {
|
|||||||
"expect_warnings",
|
"expect_warnings",
|
||||||
"expect_stdout",
|
"expect_stdout",
|
||||||
"node_version",
|
"node_version",
|
||||||
|
"reminify",
|
||||||
].indexOf(label.name) >= 0,
|
].indexOf(label.name) >= 0,
|
||||||
tmpl("Unsupported label {name} [{line},{col}]", {
|
tmpl("Unsupported label {name} [{line},{col}]", {
|
||||||
name: label.name,
|
name: label.name,
|
||||||
@@ -309,6 +327,9 @@ function parse_test(file) {
|
|||||||
var stat = node.body;
|
var stat = node.body;
|
||||||
if (label.name == "expect_exact" || label.name == "node_version") {
|
if (label.name == "expect_exact" || label.name == "node_version") {
|
||||||
test[label.name] = read_string(stat);
|
test[label.name] = read_string(stat);
|
||||||
|
} else if (label.name == "reminify") {
|
||||||
|
var value = read_boolean(stat);
|
||||||
|
test.reminify = value == null || value;
|
||||||
} else if (label.name == "expect_stdout") {
|
} else if (label.name == "expect_stdout") {
|
||||||
var body = stat.body;
|
var body = stat.body;
|
||||||
if (body instanceof U.AST_Boolean) {
|
if (body instanceof U.AST_Boolean) {
|
||||||
@@ -358,14 +379,17 @@ function evaluate(code) {
|
|||||||
function reminify(orig_options, input_code, input_formatted, expect_stdout) {
|
function reminify(orig_options, input_code, input_formatted, expect_stdout) {
|
||||||
for (var i = 0; i < minify_options.length; i++) {
|
for (var i = 0; i < minify_options.length; i++) {
|
||||||
var options = JSON.parse(minify_options[i]);
|
var options = JSON.parse(minify_options[i]);
|
||||||
if (options.compress) [
|
options.keep_fnames = orig_options.keep_fnames;
|
||||||
"keep_fargs",
|
options.keep_classnames = orig_options.keep_classnames;
|
||||||
"keep_fnames",
|
if (orig_options.compress) {
|
||||||
].forEach(function(name) {
|
options.compress.keep_classnames = orig_options.compress.keep_classnames;
|
||||||
if (name in orig_options) {
|
options.compress.keep_fargs = orig_options.compress.keep_fargs;
|
||||||
options.compress[name] = orig_options[name];
|
options.compress.keep_fnames = orig_options.compress.keep_fnames;
|
||||||
}
|
}
|
||||||
});
|
if (orig_options.mangle) {
|
||||||
|
options.mangle.keep_classnames = orig_options.mangle.keep_classnames;
|
||||||
|
options.mangle.keep_fnames = orig_options.mangle.keep_fnames;
|
||||||
|
}
|
||||||
var options_formatted = JSON.stringify(options, null, 4);
|
var options_formatted = JSON.stringify(options, null, 4);
|
||||||
var result = U.minify(input_code, options);
|
var result = U.minify(input_code, options);
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
|
|||||||
@@ -17,24 +17,30 @@ function safe_log(arg, level) {
|
|||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function strip_func_ids(text) {
|
||||||
|
return text.toString().replace(/F[0-9]{6}N/g, "<F<>N>");
|
||||||
|
}
|
||||||
|
|
||||||
var FUNC_TOSTRING = [
|
var FUNC_TOSTRING = [
|
||||||
|
"[ Array, Boolean, Error, Function, Number, Object, RegExp, String].forEach(function(f) {",
|
||||||
|
" f.toString = Function.prototype.toString;",
|
||||||
|
" f.valueOf = Function.prototype.valueOf;",
|
||||||
|
"});",
|
||||||
"Function.prototype.toString = Function.prototype.valueOf = function() {",
|
"Function.prototype.toString = Function.prototype.valueOf = function() {",
|
||||||
" var id = 100000;",
|
" var id = 100000;",
|
||||||
" return function() {",
|
" return function() {",
|
||||||
' if (this === Array) return "[Function: Array]";',
|
" var n = this.name;",
|
||||||
' if (this === Object) return "[Function: Object]";',
|
' if (!/^F[0-9]{6}N$/.test(n)) {',
|
||||||
" var i = this.name;",
|
' n = "F" + ++id + "N";',
|
||||||
' if (typeof i != "number") {',
|
|
||||||
" i = ++id;",
|
|
||||||
].concat(Object.getOwnPropertyDescriptor(Function.prototype, "name").configurable ? [
|
].concat(Object.getOwnPropertyDescriptor(Function.prototype, "name").configurable ? [
|
||||||
' Object.defineProperty(this, "name", {',
|
' Object.defineProperty(this, "name", {',
|
||||||
" get: function() {",
|
" get: function() {",
|
||||||
" return i;",
|
" return n;",
|
||||||
" }",
|
" }",
|
||||||
" });",
|
" });",
|
||||||
] : [], [
|
] : [], [
|
||||||
" }",
|
" }",
|
||||||
' return "[Function: " + i + "]";',
|
' return "[Function: " + n + "]";',
|
||||||
" }",
|
" }",
|
||||||
"}();",
|
"}();",
|
||||||
'Object.defineProperty(Function.prototype, "valueOf", { enumerable: false });',
|
'Object.defineProperty(Function.prototype, "valueOf", { enumerable: false });',
|
||||||
@@ -77,7 +83,7 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec
|
|||||||
expected = expected.message.slice(expected.message.lastIndexOf("\n") + 1);
|
expected = expected.message.slice(expected.message.lastIndexOf("\n") + 1);
|
||||||
actual = actual.message.slice(actual.message.lastIndexOf("\n") + 1);
|
actual = actual.message.slice(actual.message.lastIndexOf("\n") + 1);
|
||||||
}
|
}
|
||||||
return expected == actual;
|
return strip_func_ids(expected) == strip_func_ids(actual);
|
||||||
} : function(expected, actual) {
|
} : function(expected, actual) {
|
||||||
return typeof expected == typeof actual && expected.toString() == actual.toString();
|
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
|
||||||
};
|
};
|
||||||
|
|||||||
82
test/travis-ufuzz.js
Normal file
82
test/travis-ufuzz.js
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
var child_process = require("child_process");
|
||||||
|
var https = require("https");
|
||||||
|
var url = require("url");
|
||||||
|
|
||||||
|
var period = 45 * 60 * 1000;
|
||||||
|
var wait = 2 * 60 * 1000;
|
||||||
|
var ping = 5 * 60 * 1000;
|
||||||
|
if (process.argv[2] == "run") {
|
||||||
|
var endTime = Date.now() + period;
|
||||||
|
for (var i = 0; i < 2; i++) spawn(endTime);
|
||||||
|
} else if (process.argv.length > 2) {
|
||||||
|
var token = process.argv[2];
|
||||||
|
var branch = process.argv[3] || "v" + require("../package.json").version;
|
||||||
|
var repository = encodeURIComponent(process.argv[4] || "mishoo/UglifyJS2");
|
||||||
|
var concurrency = process.argv[5] || 1;
|
||||||
|
(function request() {
|
||||||
|
setTimeout(request, (period + wait) / concurrency);
|
||||||
|
var options = url.parse("https://api.travis-ci.org/repo/" + repository + "/requests");
|
||||||
|
options.method = "POST";
|
||||||
|
options.headers = {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Travis-API-Version": 3,
|
||||||
|
"Authorization": "token " + token
|
||||||
|
};
|
||||||
|
https.request(options, function(res) {
|
||||||
|
console.log("HTTP", res.statusCode);
|
||||||
|
console.log(JSON.stringify(res.headers, null, 2));
|
||||||
|
console.log();
|
||||||
|
res.setEncoding("utf8");
|
||||||
|
res.on("data", console.log);
|
||||||
|
}).on("error", console.error).end(JSON.stringify({
|
||||||
|
request: {
|
||||||
|
message: "ufuzz testing (when idle)",
|
||||||
|
branch: branch,
|
||||||
|
config: {
|
||||||
|
merge_mode: "replace",
|
||||||
|
language: "node_js",
|
||||||
|
node_js: "9",
|
||||||
|
sudo: false,
|
||||||
|
script: "node test/travis-ufuzz run"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
})();
|
||||||
|
} else {
|
||||||
|
console.log("Usage: test/travis-ufuzz.js <token> [branch] [repository] [concurrency]");
|
||||||
|
}
|
||||||
|
|
||||||
|
function spawn(endTime) {
|
||||||
|
var child = child_process.spawn("node", [
|
||||||
|
"--max-old-space-size=2048",
|
||||||
|
"test/ufuzz"
|
||||||
|
], {
|
||||||
|
stdio: [ "ignore", "pipe", "pipe" ]
|
||||||
|
}).on("exit", respawn);
|
||||||
|
var line = "";
|
||||||
|
child.stdout.on("data", function(data) {
|
||||||
|
line += data;
|
||||||
|
});
|
||||||
|
child.stderr.on("data", function() {
|
||||||
|
process.exitCode = 1;
|
||||||
|
}).pipe(process.stdout);
|
||||||
|
var keepAlive = setInterval(function() {
|
||||||
|
var end = line.lastIndexOf("\r");
|
||||||
|
console.log(line.slice(line.lastIndexOf("\r", end - 1) + 1, end));
|
||||||
|
line = line.slice(end + 1);
|
||||||
|
}, ping);
|
||||||
|
var timer = setTimeout(function() {
|
||||||
|
clearInterval(keepAlive);
|
||||||
|
child.removeListener("exit", respawn);
|
||||||
|
child.kill();
|
||||||
|
}, endTime - Date.now());
|
||||||
|
|
||||||
|
function respawn() {
|
||||||
|
console.log(line);
|
||||||
|
clearInterval(keepAlive);
|
||||||
|
clearTimeout(timer);
|
||||||
|
spawn(endTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -998,10 +998,11 @@ function log_suspects(minify_options, component) {
|
|||||||
if (typeof options != "object") options = {};
|
if (typeof options != "object") options = {};
|
||||||
var defs = default_options[component];
|
var defs = default_options[component];
|
||||||
var suspects = Object.keys(defs).filter(function(name) {
|
var suspects = Object.keys(defs).filter(function(name) {
|
||||||
if ((name in options ? options : defs)[name]) {
|
var flip = name == "keep_fargs";
|
||||||
|
if (flip ? name in options : (name in options ? options : defs)[name]) {
|
||||||
var m = JSON.parse(JSON.stringify(minify_options));
|
var m = JSON.parse(JSON.stringify(minify_options));
|
||||||
var o = JSON.parse(JSON.stringify(options));
|
var o = JSON.parse(JSON.stringify(options));
|
||||||
o[name] = false;
|
o[name] = flip;
|
||||||
m[component] = o;
|
m[component] = o;
|
||||||
var result = UglifyJS.minify(original_code, m);
|
var result = UglifyJS.minify(original_code, m);
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
@@ -1022,6 +1023,24 @@ function log_suspects(minify_options, component) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function log_rename(options) {
|
||||||
|
if (!options.rename) return;
|
||||||
|
var m = JSON.parse(JSON.stringify(options));
|
||||||
|
m.rename = false;
|
||||||
|
var result = UglifyJS.minify(original_code, m);
|
||||||
|
if (result.error) {
|
||||||
|
errorln("Error testing options.rename");
|
||||||
|
errorln(result.error.stack);
|
||||||
|
} else {
|
||||||
|
var r = sandbox.run_code(result.code);
|
||||||
|
if (sandbox.same_stdout(original_result, r)) {
|
||||||
|
errorln("Suspicious options:");
|
||||||
|
errorln(" rename");
|
||||||
|
errorln();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function log(options) {
|
function log(options) {
|
||||||
if (!ok) errorln('\n\n\n\n\n\n!!!!!!!!!!\n\n\n');
|
if (!ok) errorln('\n\n\n\n\n\n!!!!!!!!!!\n\n\n');
|
||||||
errorln("//=============================================================");
|
errorln("//=============================================================");
|
||||||
@@ -1056,6 +1075,7 @@ function log(options) {
|
|||||||
errorln();
|
errorln();
|
||||||
if (!ok && typeof uglify_code == "string") {
|
if (!ok && typeof uglify_code == "string") {
|
||||||
Object.keys(default_options).forEach(log_suspects.bind(null, options));
|
Object.keys(default_options).forEach(log_suspects.bind(null, options));
|
||||||
|
log_rename(options);
|
||||||
errorln("!!!!!! Failed... round " + round);
|
errorln("!!!!!! Failed... round " + round);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,8 @@
|
|||||||
"output": {
|
"output": {
|
||||||
"beautify": true,
|
"beautify": true,
|
||||||
"bracketize": true
|
"bracketize": true
|
||||||
}
|
},
|
||||||
|
"rename": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"compress": false
|
"compress": false
|
||||||
@@ -20,7 +21,13 @@
|
|||||||
{
|
{
|
||||||
"compress": {
|
"compress": {
|
||||||
"keep_fargs": false,
|
"keep_fargs": false,
|
||||||
"passes": 100
|
"passes": 1e6,
|
||||||
|
"sequences": 1e6,
|
||||||
|
"unsafe": true,
|
||||||
|
"unsafe_Function": true,
|
||||||
|
"unsafe_math": true,
|
||||||
|
"unsafe_proto": true,
|
||||||
|
"unsafe_regexp": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user