Merge branch 'master' into harmony-v3.0.25

This commit is contained in:
alexlamsl
2017-07-16 11:15:07 +08:00
16 changed files with 411 additions and 144 deletions

View File

@@ -730,7 +730,7 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
compressor from discarding function names. Useful for code relying on
`Function.prototype.name`. See also: the `keep_fnames` [mangle option](#mangle).
- `passes` -- default `1`. Number of times to run compress with a maximum of 3.
- `passes` -- default `1`. The maximum number of times to run compress.
In some cases more than one pass leads to further compressed code. Keep in
mind more passes will take more time.

View File

@@ -35,11 +35,11 @@ else if (process.argv.indexOf("options") >= 0) program.helpInformation = functio
}
return text.join("\n");
};
program.option("-p, --parse <options>", "Specify parser options.", parse_js("parse", true));
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js("compress", true));
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js("mangle", true));
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js("mangle-props", true));
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js("beautify", true));
program.option("-p, --parse <options>", "Specify parser options.", parse_js());
program.option("-c, --compress [options]", "Enable compressor/specify compressor options.", parse_js());
program.option("-m, --mangle [options]", "Mangle names/specify mangler options.", parse_js());
program.option("--mangle-props [options]", "Mangle properties/specify mangler options.", parse_js());
program.option("-b, --beautify [options]", "Beautify output/specify output options.", parse_js());
program.option("-o, --output <file>", "Output file (default STDOUT).");
program.option("--comments [filter]", "Preserve copyright comments in the output.");
program.option("--config-file <file>", "Read minify() options from JSON file.");
@@ -315,7 +315,7 @@ function read_file(path, default_value) {
}
}
function parse_js(flag, constants) {
function parse_js(flag) {
return function(value, options) {
options = options || {};
try {
@@ -333,7 +333,7 @@ function parse_js(flag, constants) {
if (node instanceof UglifyJS.AST_Assign) {
var name = node.left.print_to_string();
var value = node.right;
if (!constants) {
if (flag) {
options[name] = value;
} else if (value instanceof UglifyJS.AST_Array) {
options[name] = value.elements.map(to_string);
@@ -356,14 +356,18 @@ function parse_js(flag, constants) {
}
}));
} catch(ex) {
options[value] = null;
if (flag) {
fatal("Error parsing arguments for '" + flag + "': " + value);
} else {
options[value] = null;
}
}
return options;
}
}
function parse_source_map() {
var parse = parse_js("sourceMap", true);
var parse = parse_js();
return function(value, options) {
var hasContent = options && "content" in options;
var settings = parse(value, options);

View File

@@ -151,10 +151,20 @@ merge(Compressor.prototype, {
node.process_expression(true);
}
var passes = +this.options.passes || 1;
for (var pass = 0; pass < passes && pass < 3; ++pass) {
var last_count = 1 / 0;
for (var pass = 0; pass < passes; pass++) {
if (pass > 0 || this.option("reduce_vars"))
node.reset_opt_flags(this, true);
node = node.transform(this);
if (passes > 1) {
var count = 0;
node.walk(new TreeWalker(function() {
count++;
}));
this.info("pass " + pass + ": last_count: " + last_count + ", count: " + count);
if (count >= last_count) break;
last_count = count;
}
}
if (this.option("expression")) {
node.process_expression(false);
@@ -714,6 +724,16 @@ merge(Compressor.prototype, {
return false;
}
function is_undeclared_ref(node) {
return node instanceof AST_SymbolRef && node.definition().undeclared;
}
var global_names = makePredicate("Array Boolean console Error Function Math Number RegExp Object String");
AST_SymbolRef.DEFMETHOD("is_declared", function(compressor) {
return !this.definition().undeclared
|| compressor.option("unsafe") && global_names(this.name);
});
function tighten_body(statements, compressor) {
var CHANGED, max_iter = 10;
do {
@@ -785,7 +805,7 @@ merge(Compressor.prototype, {
|| node instanceof AST_Debugger
|| node instanceof AST_Destructuring
|| node instanceof AST_IterationStatement && !(node instanceof AST_For)
|| node instanceof AST_SymbolRef && node.undeclared()
|| node instanceof AST_SymbolRef && !node.is_declared(compressor)
|| node instanceof AST_Try
|| node instanceof AST_With
|| parent instanceof AST_For && node !== parent.init) {
@@ -817,6 +837,7 @@ merge(Compressor.prototype, {
right: candidate.value
});
}
candidate.write_only = false;
return candidate;
}
// These node types have child nodes that execute sequentially,
@@ -1389,12 +1410,12 @@ merge(Compressor.prototype, {
// returns true if this node may be null, undefined or contain `AST_Accessor`
(function(def) {
AST_Node.DEFMETHOD("may_throw_on_access", function(compressor) {
var pure_getters = compressor.option("pure_getters");
return !pure_getters || this._throw_on_access(pure_getters);
return !compressor.option("pure_getters")
|| this._dot_throw(compressor);
});
function is_strict(pure_getters) {
return /strict/.test(pure_getters);
function is_strict(compressor) {
return /strict/.test(compressor.option("pure_getters"));
}
def(AST_Node, is_strict);
@@ -1402,8 +1423,8 @@ merge(Compressor.prototype, {
def(AST_Undefined, return_true);
def(AST_Constant, return_false);
def(AST_Array, return_false);
def(AST_Object, function(pure_getters) {
if (!is_strict(pure_getters)) return false;
def(AST_Object, function(compressor) {
if (!is_strict(compressor)) return false;
for (var i = this.properties.length; --i >=0;)
if (this.properties[i].value instanceof AST_Accessor) return true;
return false;
@@ -1414,37 +1435,38 @@ merge(Compressor.prototype, {
def(AST_UnaryPrefix, function() {
return this.operator == "void";
});
def(AST_Binary, function(pure_getters) {
def(AST_Binary, function(compressor) {
switch (this.operator) {
case "&&":
return this.left._throw_on_access(pure_getters);
return this.left._dot_throw(compressor);
case "||":
return this.left._throw_on_access(pure_getters)
&& this.right._throw_on_access(pure_getters);
return this.left._dot_throw(compressor)
&& this.right._dot_throw(compressor);
default:
return false;
}
})
def(AST_Assign, function(pure_getters) {
def(AST_Assign, function(compressor) {
return this.operator == "="
&& this.right._throw_on_access(pure_getters);
&& this.right._dot_throw(compressor);
})
def(AST_Conditional, function(pure_getters) {
return this.consequent._throw_on_access(pure_getters)
|| this.alternative._throw_on_access(pure_getters);
def(AST_Conditional, function(compressor) {
return this.consequent._dot_throw(compressor)
|| this.alternative._dot_throw(compressor);
})
def(AST_Sequence, function(pure_getters) {
return this.expressions[this.expressions.length - 1]._throw_on_access(pure_getters);
def(AST_Sequence, function(compressor) {
return this.expressions[this.expressions.length - 1]._dot_throw(compressor);
});
def(AST_SymbolRef, function(pure_getters) {
def(AST_SymbolRef, function(compressor) {
if (this.is_undefined) return true;
if (!is_strict(pure_getters)) return false;
if (!is_strict(compressor)) return false;
if (is_undeclared_ref(this) && this.is_declared(compressor)) return false;
if (this.is_immutable()) return false;
var fixed = this.fixed_value();
return !fixed || fixed._throw_on_access(pure_getters);
return !fixed || fixed._dot_throw(compressor);
});
})(function(node, func) {
node.DEFMETHOD("_throw_on_access", func);
node.DEFMETHOD("_dot_throw", func);
});
/* -----[ boolean/negation helpers ]----- */
@@ -1814,11 +1836,8 @@ merge(Compressor.prototype, {
});
var global_objs = {
Array: Array,
Boolean: Boolean,
Math: Math,
Number: Number,
RegExp: RegExp,
Object: Object,
String: String,
};
function convert_to_predicate(obj) {
@@ -1855,7 +1874,7 @@ merge(Compressor.prototype, {
}
var exp = this.expression;
var val;
if (exp instanceof AST_SymbolRef && exp.undeclared()) {
if (is_undeclared_ref(exp)) {
if (!(static_values[exp.name] || return_false)(key)) return this;
val = global_objs[exp.name];
} else {
@@ -1932,10 +1951,6 @@ merge(Compressor.prototype, {
"isFinite",
"isNaN",
],
Object: [
"keys",
"getOwnPropertyNames",
],
String: [
"fromCharCode",
],
@@ -1951,7 +1966,7 @@ merge(Compressor.prototype, {
}
var val;
var e = exp.expression;
if (e instanceof AST_SymbolRef && e.undeclared()) {
if (is_undeclared_ref(e)) {
if (!(static_fns[e.name] || return_false)(key)) return this;
val = global_objs[e.name];
} else {
@@ -2139,7 +2154,7 @@ merge(Compressor.prototype, {
|| this.expression.has_side_effects(compressor);
});
def(AST_SymbolRef, function(compressor){
return this.undeclared();
return !this.is_declared(compressor);
});
def(AST_SymbolDeclaration, return_false);
def(AST_Object, function(compressor){
@@ -2271,7 +2286,12 @@ merge(Compressor.prototype, {
if (self.uses_eval || self.uses_with) return;
var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;
var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars;
var assign_as_unused = !/keep_assign/.test(compressor.option("unused"));
var assign_as_unused = /keep_assign/.test(compressor.option("unused")) ? return_false : function(node) {
if (node instanceof AST_Assign && (node.write_only || node.operator == "=")) {
return node.left;
}
if (node instanceof AST_Unary && node.write_only) return node.expression;
};
var in_use = [];
var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
if (self instanceof AST_Toplevel && compressor.top_retain) {
@@ -2335,13 +2355,9 @@ merge(Compressor.prototype, {
});
return true;
}
if (assign_as_unused
&& node instanceof AST_Assign
&& node.operator == "="
&& node.left instanceof AST_SymbolRef
&& !is_ref_of(node.left, AST_SymbolBlockDeclaration)
&& scope === self) {
node.right.walk(tw);
if (assign_as_unused(node) instanceof AST_SymbolRef && scope === self
&& !is_ref_of(node.left, AST_SymbolBlockDeclaration)) {
if (node instanceof AST_Assign) node.right.walk(tw);
return true;
}
if (node instanceof AST_SymbolRef) {
@@ -2524,15 +2540,18 @@ merge(Compressor.prototype, {
});
}
}
if (assign_as_unused
&& node instanceof AST_Assign
&& node.operator == "="
&& node.left instanceof AST_SymbolRef) {
var def = node.left.definition();
if (!(def.id in in_use_ids)
if (drop_vars) {
var def = assign_as_unused(node);
if (def instanceof AST_SymbolRef
&& !((def = def.definition()).id in in_use_ids)
&& (drop_vars || !def.global)
&& self.variables.get(def.name) === def) {
return maintain_this_binding(parent, node, node.right.transform(tt));
if (node instanceof AST_Assign) {
return maintain_this_binding(parent, node, node.right.transform(tt));
}
return make_node(AST_Number, node, {
value: 0
});
}
}
// certain combination of unused name + side effect leads to:
@@ -2785,7 +2804,10 @@ merge(Compressor.prototype, {
return make_sequence(this, [ left, right ]);
}
});
def(AST_Assign, return_this);
def(AST_Assign, function(compressor){
this.write_only = !this.left.has_side_effects(compressor);
return this;
});
def(AST_Conditional, function(compressor){
var consequent = this.consequent.drop_side_effect_free(compressor);
var alternative = this.alternative.drop_side_effect_free(compressor);
@@ -2806,7 +2828,10 @@ merge(Compressor.prototype, {
return node;
});
def(AST_Unary, function(compressor, first_in_statement){
if (unary_side_effects(this.operator)) return this;
if (unary_side_effects(this.operator)) {
this.write_only = !this.expression.has_side_effects(compressor);
return this;
}
if (this.operator == "typeof" && this.expression instanceof AST_SymbolRef) return null;
var expression = this.expression.drop_side_effect_free(compressor, first_in_statement);
if (first_in_statement
@@ -2820,8 +2845,8 @@ merge(Compressor.prototype, {
}
return expression;
});
def(AST_SymbolRef, function() {
return this.undeclared() ? this : null;
def(AST_SymbolRef, function(compressor) {
return this.is_declared(compressor) ? null : this;
});
def(AST_Object, function(compressor, first_in_statement){
var values = trim(this.properties, compressor, first_in_statement);
@@ -3316,7 +3341,7 @@ merge(Compressor.prototype, {
self.args.length = last;
}
if (compressor.option("unsafe")) {
if (exp instanceof AST_SymbolRef && exp.undeclared()) {
if (is_undeclared_ref(exp)) {
switch (exp.name) {
case "Array":
if (self.args.length != 1) {
@@ -3447,8 +3472,7 @@ merge(Compressor.prototype, {
}
}
if (compressor.option("unsafe_Func")
&& exp instanceof AST_SymbolRef
&& exp.undeclared()
&& is_undeclared_ref(exp)
&& exp.name == "Function") {
// new Function() => function(){}
if (self.args.length == 0) return make_node(AST_Function, self, {
@@ -3581,9 +3605,7 @@ merge(Compressor.prototype, {
while (name.expression) {
name = name.expression;
}
if (name instanceof AST_SymbolRef
&& name.name == "console"
&& name.undeclared()) {
if (is_undeclared_ref(name) && name.name == "console") {
return make_node(AST_Undefined, self).optimize(compressor);
}
}
@@ -3604,7 +3626,7 @@ merge(Compressor.prototype, {
OPT(AST_New, function(self, compressor){
if (compressor.option("unsafe")) {
var exp = self.expression;
if (exp instanceof AST_SymbolRef && exp.undeclared()) {
if (is_undeclared_ref(exp)) {
switch (exp.name) {
case "Object":
case "RegExp":
@@ -3681,6 +3703,8 @@ merge(Compressor.prototype, {
operator: car.operator,
expression: left
});
} else {
car.write_only = false;
}
if (parent) {
parent[field] = car;
@@ -3896,7 +3920,7 @@ merge(Compressor.prototype, {
&& self.right instanceof AST_UnaryPrefix
&& self.right.operator == "typeof") {
var expr = self.right.expression;
if (expr instanceof AST_SymbolRef ? !expr.undeclared()
if (expr instanceof AST_SymbolRef ? expr.is_declared(compressor)
: !(expr instanceof AST_PropAccess && compressor.option("ie8"))) {
self.right = expr;
self.left = make_node(AST_Undefined, self.left).optimize(compressor);
@@ -4226,7 +4250,7 @@ merge(Compressor.prototype, {
}
// testing against !self.scope.uses_with first is an optimization
if (!compressor.option("ie8")
&& self.undeclared()
&& is_undeclared_ref(self)
&& (!self.scope.uses_with || !compressor.find_parent(AST_With))) {
switch (self.name) {
case "undefined":
@@ -4598,7 +4622,7 @@ merge(Compressor.prototype, {
var prop = self.property;
if (prop instanceof AST_String && compressor.option("properties")) {
prop = prop.getValue();
if (RESERVED_WORDS(prop) ? !compressor.option("ie8") : is_identifier_string(prop)) {
if (is_identifier_string(prop)) {
return make_node(AST_Dot, self, {
expression : self.expression,
property : prop
@@ -4635,20 +4659,11 @@ merge(Compressor.prototype, {
if (def) {
return def.optimize(compressor);
}
var prop = self.property;
if (RESERVED_WORDS(prop) && compressor.option("ie8")) {
return make_node(AST_Sub, self, {
expression : self.expression,
property : make_node(AST_String, self, {
value: prop
})
}).optimize(compressor);
}
if (compressor.option("unsafe") && self.expression instanceof AST_Object) {
var values = self.expression.properties;
for (var i = values.length; --i >= 0;) {
var key = values[i].key;
if ((key instanceof AST_SymbolMethod ? key.name : key) === prop) {
if ((key instanceof AST_SymbolMethod ? key.name : key) === self.property) {
var value = values[i].value;
if (key instanceof AST_SymbolMethod) {
if (values[i].is_generator) break;
@@ -4667,7 +4682,7 @@ merge(Compressor.prototype, {
&& self.expression instanceof AST_Dot
&& self.expression.property == "prototype") {
var exp = self.expression.expression;
if (exp instanceof AST_SymbolRef && exp.undeclared()) switch (exp.name) {
if (is_undeclared_ref(exp)) switch (exp.name) {
case "Array":
self.expression = make_node(AST_Array, self.expression, {
elements: []

View File

@@ -1400,6 +1400,9 @@ function OutputStream(options) {
self.expression.print(output);
if (self instanceof AST_New && !need_constructor_parens(self, output))
return;
if (self.expression instanceof AST_Lambda) {
output.add_mapping(self.start);
}
output.with_parens(function(){
self.args.forEach(function(expr, i){
if (i) output.comma();
@@ -1439,15 +1442,23 @@ function OutputStream(options) {
DEFPRINT(AST_Dot, function(self, output){
var expr = self.expression;
expr.print(output);
if (expr instanceof AST_Number && expr.getValue() >= 0) {
if (!/[xa-f.)]/i.test(output.last())) {
output.print(".");
var prop = self.property;
if (output.option("ie8") && RESERVED_WORDS(prop)) {
output.print("[");
output.add_mapping(self.end);
output.print_string(prop);
output.print("]");
} else {
if (expr instanceof AST_Number && expr.getValue() >= 0) {
if (!/[xa-f.)]/i.test(output.last())) {
output.print(".");
}
}
output.print(".");
// the name after dot would be mapped about here.
output.add_mapping(self.end);
output.print_name(prop);
}
output.print(".");
// the name after dot would be mapped about here.
output.add_mapping(self.end);
output.print_name(self.property);
});
DEFPRINT(AST_Sub, function(self, output){
self.expression.print(output);

View File

@@ -94,7 +94,7 @@ function mangle_properties(ast, options) {
only_cache: false,
regex: null,
reserved: null,
});
}, true);
var reserved = options.reserved;
if (!Array.isArray(reserved)) reserved = [];

View File

@@ -461,14 +461,6 @@ AST_Symbol.DEFMETHOD("unreferenced", function(){
&& !(this.scope.uses_eval || this.scope.uses_with);
});
AST_Symbol.DEFMETHOD("undeclared", function(){
return this.definition().undeclared;
});
AST_LabelRef.DEFMETHOD("undeclared", return_false);
AST_Label.DEFMETHOD("undeclared", return_false);
AST_Symbol.DEFMETHOD("definition", function(){
return this.thedef;
});

View File

@@ -4,7 +4,7 @@
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.0.24",
"version": "3.0.25",
"engines": {
"node": ">=0.8.0"
},

View File

@@ -6,6 +6,7 @@
var createHash = require("crypto").createHash;
var fetch = require("./fetch");
var fork = require("child_process").fork;
var zlib = require("zlib");
var args = process.argv.slice(2);
if (!args.length) {
args.push("-mc");
@@ -33,6 +34,7 @@ function done() {
console.log(info.log);
console.log("Original:", info.input, "bytes");
console.log("Uglified:", info.output, "bytes");
console.log("GZipped: ", info.gzip, "bytes");
console.log("SHA1 sum:", info.sha1);
if (info.code) {
failures.push(url);
@@ -51,6 +53,7 @@ urls.forEach(function(url) {
results[url] = {
input: 0,
output: 0,
gzip: 0,
log: ""
};
fetch(url, function(err, res) {
@@ -61,6 +64,10 @@ urls.forEach(function(url) {
}).pipe(uglifyjs.stdin);
uglifyjs.stdout.on("data", function(data) {
results[url].output += data.length;
}).pipe(zlib.createGzip({
level: zlib.Z_BEST_COMPRESSION
})).on("data", function(data) {
results[url].gzip += data.length;
}).pipe(createHash("sha1")).on("data", function(data) {
results[url].sha1 = data.toString("hex");
done();

View File

@@ -863,7 +863,7 @@ collapse_vars_unary: {
input: {
function f0(o, p) {
var x = o[p];
delete x;
return delete x;
}
function f1(n) {
var k = !!n;
@@ -893,7 +893,7 @@ collapse_vars_unary: {
expect: {
function f0(o, p) {
var x = o[p];
delete x;
return delete x;
}
function f1(n) {
return n > +!!n

View File

@@ -377,3 +377,82 @@ accessor: {
}
expect: {}
}
issue_2233_1: {
options = {
pure_getters: "strict",
side_effects: true,
unsafe: true,
}
input: {
Array.isArray;
Boolean;
console.log;
Error.name;
Function.length;
Math.random;
Number.isNaN;
RegExp;
Object.defineProperty;
String.fromCharCode;
}
expect: {}
expect_stdout: true
}
issue_2233_2: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
unsafe: true,
unused: true,
}
input: {
var RegExp;
Array.isArray;
RegExp;
UndeclaredGlobal;
function foo() {
var Number;
AnotherUndeclaredGlobal;
Math.sin;
Number.isNaN;
}
}
expect: {
var RegExp;
UndeclaredGlobal;
function foo() {
var Number;
AnotherUndeclaredGlobal;
Number.isNaN;
}
}
}
issue_2233_3: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
var RegExp;
Array.isArray;
RegExp;
UndeclaredGlobal;
function foo() {
var Number;
AnotherUndeclaredGlobal;
Math.sin;
Number.isNaN;
}
}
expect: {
UndeclaredGlobal;
}
}

View File

@@ -1210,6 +1210,7 @@ var_catch_toplevel: {
a--;
try {
a++;
x();
} catch(a) {
if (a) var a;
var a = 10;
@@ -1219,9 +1220,8 @@ var_catch_toplevel: {
}
expect: {
!function() {
a--;
try {
a++;
x();
} catch(a) {
var a;
}
@@ -1427,3 +1427,89 @@ issue_2163: {
b;
}
}
issue_2226_1: {
options = {
side_effects: true,
unused: true,
}
input: {
function f1() {
var a = b;
a += c;
}
function f2(a) {
a <<= b;
}
function f3(a) {
--a;
}
function f4() {
var a = b;
return a *= c;
}
function f5(a) {
x(a /= b);
}
}
expect: {
function f1() {
b;
c;
}
function f2(a) {
b;
}
function f3(a) {
0;
}
function f4() {
var a = b;
return a *= c;
}
function f5(a) {
x(a /= b);
}
}
}
issue_2226_2: {
options = {
cascade: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
console.log(function(a, b) {
a += b;
return a;
}(1, 2));
}
expect: {
console.log(function(a, b) {
return a += b;
}(1, 2));
}
expect_stdout: "3"
}
issue_2226_3: {
options = {
collapse_vars: true,
side_effects: true,
unused: true,
}
input: {
console.log(function(a, b) {
a += b;
return a;
}(1, 2));
}
expect: {
console.log(function(a, b) {
return a += 2;
}(1));
}
expect_stdout: "3"
}

View File

@@ -1250,3 +1250,31 @@ issue_2207_3: {
}
expect_stdout: true
}
issue_2231_1: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(Object.keys(void 0));
}
expect: {
console.log(Object.keys(void 0));
}
expect_stdout: true
}
issue_2231_2: {
options = {
evaluate: true,
unsafe: true,
}
input: {
console.log(Object.getOwnPropertyNames(null));
}
expect: {
console.log(Object.getOwnPropertyNames(null));
}
expect_stdout: true
}

View File

@@ -71,11 +71,13 @@ non_hoisted_function_after_return_2a: {
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:51,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:48,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:55,21]",
"WARN: pass 0: last_count: Infinity, count: 37",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:53,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:53,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:56,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:51,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:53,16]",
"WARN: pass 1: last_count: 37, count: 18",
]
}
@@ -109,11 +111,11 @@ non_hoisted_function_after_return_2b: {
}
expect_warnings: [
// duplicate warnings no longer emitted
"WARN: Dropping unreachable code [test/compress/issue-1034.js:95,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:95,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:101,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:97,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:97,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:99,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:99,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:103,12]",
]
}
@@ -151,10 +153,10 @@ non_hoisted_function_after_return_strict: {
}
expect_stdout: "8 7"
expect_warnings: [
'WARN: Dropping unreachable code [test/compress/issue-1034.js:131,16]',
"WARN: Dropping unreachable code [test/compress/issue-1034.js:134,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:137,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:138,21]"
"WARN: Dropping unreachable code [test/compress/issue-1034.js:133,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:136,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:139,12]",
"WARN: Dropping unused function UnusedFunction [test/compress/issue-1034.js:140,21]",
]
}
@@ -194,17 +196,19 @@ non_hoisted_function_after_return_2a_strict: {
}
expect_stdout: "5 6"
expect_warnings: [
"WARN: Dropping unreachable code [test/compress/issue-1034.js:173,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:173,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:176,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:176,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:173,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:180,21]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:178,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:178,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:181,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:176,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:178,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:175,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:175,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:178,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:178,16]",
"WARN: Dropping unused variable a [test/compress/issue-1034.js:175,20]",
"WARN: Dropping unused function nope [test/compress/issue-1034.js:182,21]",
"WARN: pass 0: last_count: Infinity, count: 48",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:180,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:180,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:183,12]",
"WARN: Dropping unused variable b [test/compress/issue-1034.js:178,20]",
"WARN: Dropping unused variable c [test/compress/issue-1034.js:180,16]",
"WARN: pass 1: last_count: 48, count: 29",
]
}
@@ -243,10 +247,10 @@ non_hoisted_function_after_return_2b_strict: {
expect_stdout: "5 6"
expect_warnings: [
// duplicate warnings no longer emitted
"WARN: Dropping unreachable code [test/compress/issue-1034.js:225,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:225,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:227,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:227,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:229,16]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:229,16]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:231,12]",
"WARN: Declarations in unreachable code! [test/compress/issue-1034.js:231,12]",
"WARN: Dropping unreachable code [test/compress/issue-1034.js:235,12]",
]
}

View File

@@ -13,8 +13,10 @@ keep_properties: {
dot_properties: {
options = {
properties: true,
}
beautify = {
ie8: true,
};
}
input: {
a["foo"] = "bar";
a["if"] = "if";
@@ -36,8 +38,10 @@ dot_properties: {
dot_properties_es5: {
options = {
properties: true,
}
beautify = {
ie8: false,
};
}
input: {
a["foo"] = "bar";
a["if"] = "if";

View File

@@ -66,7 +66,7 @@ describe("bin/uglifyjs", function () {
if (err) throw err;
assert.strictEqual(stdout, "var bar=function(){function foo(bar){return bar}return foo}();\n" +
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DIn0=\n");
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==\n");
done();
});
});
@@ -195,7 +195,7 @@ describe("bin/uglifyjs", function () {
assert.strictEqual(stdout, [
"var bar=function(){function foo(bar){return bar}return foo}();",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DIn0=",
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlc3QvaW5wdXQvaXNzdWUtMTMyMy9zYW1wbGUuanMiXSwibmFtZXMiOlsiYmFyIiwiZm9vIl0sIm1hcHBpbmdzIjoiQUFBQSxJQUFJQSxJQUFNLFdBQ04sU0FBU0MsSUFBS0QsS0FDVixPQUFPQSxJQUdYLE9BQU9DLElBTEQifQ==",
"",
].join("\n"));
assert.strictEqual(stderr, "WARN: inline source map not found\n");
@@ -686,8 +686,8 @@ describe("bin/uglifyjs", function () {
done();
});
});
it("Should work with --mangle reserved=[]", function (done) {
var command = uglifyjscmd + ' test/input/issue-505/input.js -m reserved=[callback]';
it("Should work with --mangle reserved=[]", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=[callback]";
exec(command, function (err, stdout) {
if (err) throw err;
@@ -696,8 +696,8 @@ describe("bin/uglifyjs", function () {
done();
});
});
it("Should work with --mangle reserved=false", function (done) {
var command = uglifyjscmd + ' test/input/issue-505/input.js -m reserved=false';
it("Should work with --mangle reserved=false", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=false";
exec(command, function (err, stdout) {
if (err) throw err;
@@ -706,4 +706,22 @@ describe("bin/uglifyjs", function () {
done();
});
});
it("Should fail with --mangle-props reserved=[in]", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js --mangle-props reserved=[in]";
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.ok(/^Supported options:\n[\s\S]*?\nERROR: `reserved=\[in]` is not a supported option/.test(stderr), stderr);
done();
});
});
it("Should fail with --define a-b", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js --define a-b";
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
assert.strictEqual(stderr, "Error parsing arguments for 'define': a-b\n");
done();
});
});
});

View File

@@ -2,16 +2,17 @@ var Uglify = require('../../');
var assert = require("assert");
describe("let", function() {
it("Should not produce reserved keywords as variable name in mangle", function(done) {
this.timeout(10000);
this.timeout(30000);
it("Should not produce reserved keywords as variable name in mangle", function() {
// Produce a lot of variables in a function and run it through mangle.
var s = '"dddddeeeeelllllooooottttt"; function foo() {';
for (var i = 0; i < 18000; i++) {
s += "var v" + i + "=0;";
}
s += '}';
var result = Uglify.minify(s, {compress: false});
var result = Uglify.minify(s, {
compress: false
}).code;
// Verify that select keywords and reserved keywords not produced
[
@@ -19,7 +20,7 @@ describe("let", function() {
"let",
"var",
].forEach(function(name) {
assert.strictEqual(result.code.indexOf("var " + name + "="), -1);
assert.strictEqual(result.indexOf("var " + name + "="), -1);
});
// Verify that the variable names that appeared immediately before
@@ -30,9 +31,27 @@ describe("let", function() {
"eet", "fet",
"rar", "oar",
].forEach(function(name) {
assert.ok(result.code.indexOf("var " + name + "=") >= 0);
assert.notStrictEqual(result.indexOf("var " + name + "="), -1);
});
});
it("Should quote mangled properties that are reserved keywords", function() {
var s = '"rrrrrnnnnniiiiiaaaaa";';
for (var i = 0; i < 18000; i++) {
s += "v.b" + i + ";";
}
var result = Uglify.minify(s, {
compress: false,
ie8: true,
mangle: {
properties: true,
}
}).code;
[
"in",
"var",
].forEach(function(name) {
assert.notStrictEqual(result.indexOf(name), -1);
assert.notStrictEqual(result.indexOf('v["' + name + '"]'), -1);
});
done();
});
});