Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b23b333d9d | ||
|
|
7621527a5f | ||
|
|
1a064b6e74 | ||
|
|
82772ccb12 | ||
|
|
7cbcd11440 | ||
|
|
980dbde171 | ||
|
|
8b05677c15 | ||
|
|
95090dbf24 | ||
|
|
7c5b6f349e | ||
|
|
e9c902b044 | ||
|
|
111366fca0 | ||
|
|
e368d39715 | ||
|
|
fd8dec61ad | ||
|
|
7880568d15 | ||
|
|
21fc8f4630 | ||
|
|
bf76e35772 | ||
|
|
ac1262dc97 | ||
|
|
498ac83541 | ||
|
|
6fc7a2ab6a | ||
|
|
f8b2215145 | ||
|
|
70ceda5398 | ||
|
|
ce75477670 | ||
|
|
e70b84895c |
@@ -344,9 +344,9 @@ function run() {
|
|||||||
var list = annotations[node.start.file];
|
var list = annotations[node.start.file];
|
||||||
var pure = list[node.start.pos];
|
var pure = list[node.start.pos];
|
||||||
if (!pure) {
|
if (!pure) {
|
||||||
var pos = node.start.parens;
|
var tokens = node.start.parens;
|
||||||
if (pos) for (var i = 0; !pure && i < pos.length; i++) {
|
if (tokens) for (var i = 0; !pure && i < tokens.length; i++) {
|
||||||
pure = list[pos[i]];
|
pure = list[tokens[i].pos];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pure) node.pure = pure;
|
if (pure) node.pure = pure;
|
||||||
|
|||||||
40
lib/ast.js
40
lib/ast.js
@@ -56,35 +56,31 @@ function DEFNODE(type, props, methods, base) {
|
|||||||
code.push("this.", prop, "=props.", prop, ";");
|
code.push("this.", prop, "=props.", prop, ";");
|
||||||
});
|
});
|
||||||
code.push("}");
|
code.push("}");
|
||||||
var proto = base && new base;
|
var proto = Object.create(base && base.prototype);
|
||||||
if (proto && proto.initialize || methods && methods.initialize) code.push("this.initialize();");
|
if (methods.initialize || proto.initialize) code.push("this.initialize();");
|
||||||
code.push("}");
|
code.push("};");
|
||||||
var ctor = new Function(code.join(""))();
|
var ctor = new Function(code.join(""))();
|
||||||
if (proto) {
|
ctor.prototype = proto;
|
||||||
ctor.prototype = proto;
|
|
||||||
ctor.BASE = base;
|
|
||||||
}
|
|
||||||
if (base) base.SUBCLASSES.push(ctor);
|
|
||||||
ctor.prototype.CTOR = ctor;
|
ctor.prototype.CTOR = ctor;
|
||||||
ctor.PROPS = props || null;
|
ctor.prototype.TYPE = ctor.TYPE = type;
|
||||||
ctor.SELF_PROPS = self_props;
|
if (base) {
|
||||||
ctor.SUBCLASSES = [];
|
ctor.BASE = base;
|
||||||
if (type) {
|
base.SUBCLASSES.push(ctor);
|
||||||
ctor.prototype.TYPE = ctor.TYPE = type;
|
|
||||||
}
|
|
||||||
if (methods) for (var name in methods) if (HOP(methods, name)) {
|
|
||||||
if (/^\$/.test(name)) {
|
|
||||||
ctor[name.substr(1)] = methods[name];
|
|
||||||
} else {
|
|
||||||
ctor.prototype[name] = methods[name];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ctor.DEFMETHOD = function(name, method) {
|
ctor.DEFMETHOD = function(name, method) {
|
||||||
this.prototype[name] = method;
|
this.prototype[name] = method;
|
||||||
};
|
};
|
||||||
if (typeof exports !== "undefined") {
|
ctor.PROPS = props;
|
||||||
exports["AST_" + type] = ctor;
|
ctor.SELF_PROPS = self_props;
|
||||||
|
ctor.SUBCLASSES = [];
|
||||||
|
for (var name in methods) if (HOP(methods, name)) {
|
||||||
|
if (/^\$/.test(name)) {
|
||||||
|
ctor[name.substr(1)] = methods[name];
|
||||||
|
} else {
|
||||||
|
ctor.DEFMETHOD(name, methods[name]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (typeof exports !== "undefined") exports["AST_" + type] = ctor;
|
||||||
return ctor;
|
return ctor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
503
lib/compress.js
503
lib/compress.js
@@ -108,6 +108,7 @@ function Compressor(options, false_by_default) {
|
|||||||
unsafe_undefined: false,
|
unsafe_undefined: false,
|
||||||
unused : !false_by_default,
|
unused : !false_by_default,
|
||||||
varify : !false_by_default,
|
varify : !false_by_default,
|
||||||
|
webkit : false,
|
||||||
yields : !false_by_default,
|
yields : !false_by_default,
|
||||||
}, true);
|
}, true);
|
||||||
var evaluate = this.options["evaluate"];
|
var evaluate = this.options["evaluate"];
|
||||||
@@ -606,7 +607,11 @@ merge(Compressor.prototype, {
|
|||||||
var safe = tw.safe_ids[def.id];
|
var safe = tw.safe_ids[def.id];
|
||||||
if (!HOP(tw.safe_ids, def.id)) {
|
if (!HOP(tw.safe_ids, def.id)) {
|
||||||
if (!safe) return false;
|
if (!safe) return false;
|
||||||
if (safe.read && def.scope.resolve() !== tw.find_parent(AST_Scope)) return false;
|
if (safe.read) {
|
||||||
|
var scope = tw.find_parent(AST_BlockScope);
|
||||||
|
if (scope instanceof AST_Class) return false;
|
||||||
|
if (def.scope.resolve() !== scope.resolve()) return false;
|
||||||
|
}
|
||||||
safe.assign = safe.assign && safe.assign !== tw.safe_ids ? true : tw.safe_ids;
|
safe.assign = safe.assign && safe.assign !== tw.safe_ids ? true : tw.safe_ids;
|
||||||
}
|
}
|
||||||
if (def.fixed != null && safe.read) {
|
if (def.fixed != null && safe.read) {
|
||||||
@@ -1008,6 +1013,11 @@ merge(Compressor.prototype, {
|
|||||||
reset_def(tw, compressor, def);
|
reset_def(tw, compressor, def);
|
||||||
});
|
});
|
||||||
if (node.extends) node.extends.walk(tw);
|
if (node.extends) node.extends.walk(tw);
|
||||||
|
var props = node.properties.filter(function(prop) {
|
||||||
|
reset_flags(prop);
|
||||||
|
if (prop.key instanceof AST_Node) prop.key.walk(tw);
|
||||||
|
return prop.value;
|
||||||
|
});
|
||||||
if (node.name) {
|
if (node.name) {
|
||||||
var d = node.name.definition();
|
var d = node.name.definition();
|
||||||
var parent = tw.parent();
|
var parent = tw.parent();
|
||||||
@@ -1024,11 +1034,7 @@ merge(Compressor.prototype, {
|
|||||||
d.fixed = false;
|
d.fixed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.properties.filter(function(prop) {
|
props.forEach(function(prop) {
|
||||||
reset_flags(prop);
|
|
||||||
if (prop.key instanceof AST_Node) prop.key.walk(tw);
|
|
||||||
return prop.value;
|
|
||||||
}).forEach(function(prop) {
|
|
||||||
if (!prop.static || prop instanceof AST_ClassField && prop.value.contains_this()) {
|
if (!prop.static || prop instanceof AST_ClassField && prop.value.contains_this()) {
|
||||||
push(tw);
|
push(tw);
|
||||||
prop.value.walk(tw);
|
prop.value.walk(tw);
|
||||||
@@ -1506,7 +1512,7 @@ merge(Compressor.prototype, {
|
|||||||
function is_lhs_read_only(lhs, compressor) {
|
function is_lhs_read_only(lhs, compressor) {
|
||||||
if (lhs instanceof AST_ObjectIdentity) return true;
|
if (lhs instanceof AST_ObjectIdentity) return true;
|
||||||
if (lhs instanceof AST_PropAccess) {
|
if (lhs instanceof AST_PropAccess) {
|
||||||
if (lhs.property == "__proto__") return true;
|
if (lhs.property === "__proto__") return true;
|
||||||
lhs = lhs.expression;
|
lhs = lhs.expression;
|
||||||
if (lhs instanceof AST_SymbolRef) {
|
if (lhs instanceof AST_SymbolRef) {
|
||||||
if (lhs.is_immutable()) return false;
|
if (lhs.is_immutable()) return false;
|
||||||
@@ -1710,6 +1716,15 @@ merge(Compressor.prototype, {
|
|||||||
return stat instanceof AST_LambdaDefinition;
|
return stat instanceof AST_LambdaDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function is_last_statement(body, stat) {
|
||||||
|
var index = body.lastIndexOf(stat);
|
||||||
|
if (index < 0) return false;
|
||||||
|
while (++index < body.length) {
|
||||||
|
if (!is_declaration(body[index], true)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
function tighten_body(statements, compressor) {
|
function tighten_body(statements, compressor) {
|
||||||
var in_loop, in_try, scope;
|
var in_loop, in_try, scope;
|
||||||
find_loop_scope_try();
|
find_loop_scope_try();
|
||||||
@@ -1804,10 +1819,7 @@ merge(Compressor.prototype, {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (is_lhs(node, parent)) {
|
if (is_lhs(node, parent)) {
|
||||||
if (value_def && !hit_rhs) {
|
if (value_def && !hit_rhs) assign_used = true;
|
||||||
assign_used = true;
|
|
||||||
replaced++;
|
|
||||||
}
|
|
||||||
return node;
|
return node;
|
||||||
} else if (value_def) {
|
} else if (value_def) {
|
||||||
if (stop_if_hit && assign_pos == 0) assign_pos = remaining - replaced;
|
if (stop_if_hit && assign_pos == 0) assign_pos = remaining - replaced;
|
||||||
@@ -1932,10 +1944,9 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Replace variable when found
|
// Replace variable when found
|
||||||
if (node instanceof AST_SymbolRef
|
if (node instanceof AST_SymbolRef && node.definition() === def) {
|
||||||
&& node.name == def.name) {
|
|
||||||
if (!--replaced) abort = true;
|
|
||||||
if (is_lhs(node, multi_replacer.parent())) return node;
|
if (is_lhs(node, multi_replacer.parent())) return node;
|
||||||
|
if (!--replaced) abort = true;
|
||||||
var ref = rvalue.clone();
|
var ref = rvalue.clone();
|
||||||
ref.scope = node.scope;
|
ref.scope = node.scope;
|
||||||
ref.reference();
|
ref.reference();
|
||||||
@@ -2011,7 +2022,7 @@ merge(Compressor.prototype, {
|
|||||||
statements[i].transform(scanner);
|
statements[i].transform(scanner);
|
||||||
}
|
}
|
||||||
if (value_def) {
|
if (value_def) {
|
||||||
if (!replaced || remaining > replaced) {
|
if (!replaced || remaining > replaced + assign_used) {
|
||||||
candidates.push(hit_stack);
|
candidates.push(hit_stack);
|
||||||
force_single = true;
|
force_single = true;
|
||||||
continue;
|
continue;
|
||||||
@@ -3164,15 +3175,6 @@ merge(Compressor.prototype, {
|
|||||||
return !value || value instanceof AST_UnaryPrefix && value.operator == "void";
|
return !value || value instanceof AST_UnaryPrefix && value.operator == "void";
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_last_statement(body, stat) {
|
|
||||||
var index = body.lastIndexOf(stat);
|
|
||||||
if (index < 0) return false;
|
|
||||||
while (++index < body.length) {
|
|
||||||
if (!is_declaration(body[index], true)) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
function last_of(predicate) {
|
function last_of(predicate) {
|
||||||
var block = self, stat, level = 0;
|
var block = self, stat, level = 0;
|
||||||
do {
|
do {
|
||||||
@@ -3838,7 +3840,7 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Object, function(compressor, force) {
|
def(AST_Object, function(compressor, force) {
|
||||||
return is_strict(compressor, force) && !all(this.properties, function(prop) {
|
return is_strict(compressor, force) && !all(this.properties, function(prop) {
|
||||||
if (!(prop instanceof AST_ObjectKeyVal)) return false;
|
if (!(prop instanceof AST_ObjectKeyVal)) return false;
|
||||||
return !(prop.key == "__proto__" && prop.value._dot_throw(compressor, force));
|
return !(prop.key === "__proto__" && prop.value._dot_throw(compressor, force));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
def(AST_ObjectIdentity, function(compressor, force) {
|
def(AST_ObjectIdentity, function(compressor, force) {
|
||||||
@@ -5271,7 +5273,7 @@ merge(Compressor.prototype, {
|
|||||||
|| any(this.body, compressor);
|
|| any(this.body, compressor);
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(compressor) {
|
def(AST_SymbolRef, function(compressor) {
|
||||||
return !this.is_declared(compressor);
|
return !this.is_declared(compressor) || !can_drop_symbol(this, compressor);
|
||||||
});
|
});
|
||||||
def(AST_Template, function(compressor) {
|
def(AST_Template, function(compressor) {
|
||||||
if (any(this.expressions, compressor)) return true;
|
if (any(this.expressions, compressor)) return true;
|
||||||
@@ -5856,6 +5858,7 @@ merge(Compressor.prototype, {
|
|||||||
if (head_refs.start.block !== tail_refs.start.block
|
if (head_refs.start.block !== tail_refs.start.block
|
||||||
|| !mergeable(head_refs, tail_refs)
|
|| !mergeable(head_refs, tail_refs)
|
||||||
|| (head_refs.start.loop || !same_scope(def)) && !mergeable(tail_refs, head_refs)
|
|| (head_refs.start.loop || !same_scope(def)) && !mergeable(tail_refs, head_refs)
|
||||||
|
|| compressor.option("webkit") && is_funarg(def) !== is_funarg(tail.definition)
|
||||||
|| !all(tail_refs, function(sym) {
|
|| !all(tail_refs, function(sym) {
|
||||||
return sym.scope.find_variable(def.name) === def;
|
return sym.scope.find_variable(def.name) === def;
|
||||||
})) {
|
})) {
|
||||||
@@ -6042,27 +6045,16 @@ merge(Compressor.prototype, {
|
|||||||
function compose(child, level, find) {
|
function compose(child, level, find) {
|
||||||
var parent = compressor.parent(level);
|
var parent = compressor.parent(level);
|
||||||
if (!parent) return find;
|
if (!parent) return find;
|
||||||
if (parent instanceof AST_DestructuredKeyVal) {
|
var in_arg = parent instanceof AST_Lambda && member(child, parent.argnames);
|
||||||
var destructured = compressor.parent(level + 1);
|
return compose(parent, level + 1, in_arg ? function(name) {
|
||||||
if (parent.key === child) {
|
var def = find(name);
|
||||||
var fn = compressor.parent(level + 2);
|
if (def) return def;
|
||||||
if (fn instanceof AST_Lambda) {
|
def = parent.variables.get(name);
|
||||||
return compose(fn, level + 3, fn.argnames.indexOf(destructured) >= 0 ? function(name) {
|
if (def) {
|
||||||
var def = find(name);
|
var sym = def.orig[0];
|
||||||
if (def) return def;
|
if (sym instanceof AST_SymbolFunarg || sym instanceof AST_SymbolLambda) return def;
|
||||||
def = fn.variables.get(name);
|
|
||||||
if (def) {
|
|
||||||
var sym = def.orig[0];
|
|
||||||
if (sym instanceof AST_SymbolFunarg || sym instanceof AST_SymbolLambda) return def;
|
|
||||||
}
|
|
||||||
} : function(name) {
|
|
||||||
return find(name) || fn.variables.get(name);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return compose(destructured, level + 2, find);
|
} : parent.variables ? function(name) {
|
||||||
}
|
|
||||||
return compose(parent, level + 1, parent.variables ? function(name) {
|
|
||||||
return find(name) || parent.variables.get(name);
|
return find(name) || parent.variables.get(name);
|
||||||
} : find);
|
} : find);
|
||||||
}
|
}
|
||||||
@@ -6570,10 +6562,23 @@ merge(Compressor.prototype, {
|
|||||||
if (def.orig.length > 1) return null;
|
if (def.orig.length > 1) return null;
|
||||||
if (def.assignments > 0) return false;
|
if (def.assignments > 0) return false;
|
||||||
if (def.name == name) return def;
|
if (def.name == name) return def;
|
||||||
if (name == "await" && is_async(fn)) return false;
|
var forbidden;
|
||||||
if (name == "yield" && is_generator(fn)) return false;
|
switch (name) {
|
||||||
|
case "await":
|
||||||
|
forbidden = is_async;
|
||||||
|
break;
|
||||||
|
case "yield":
|
||||||
|
forbidden = is_generator;
|
||||||
|
break;
|
||||||
|
}
|
||||||
return all(def.references, function(ref) {
|
return all(def.references, function(ref) {
|
||||||
return ref.scope.find_variable(name) === sym;
|
var scope = ref.scope;
|
||||||
|
if (scope.find_variable(name) !== sym) return false;
|
||||||
|
if (forbidden) do {
|
||||||
|
scope = scope.resolve();
|
||||||
|
if (forbidden(scope)) return false;
|
||||||
|
} while (scope !== fn && (scope = scope.parent_scope));
|
||||||
|
return true;
|
||||||
}) && def;
|
}) && def;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6734,7 +6739,7 @@ merge(Compressor.prototype, {
|
|||||||
return insert_statements(body, node, in_list);
|
return insert_statements(body, node, in_list);
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Import) {
|
if (node instanceof AST_Import) {
|
||||||
if (node.properties && node.properties == 0) node.properties = null;
|
if (node.properties && node.properties.length == 0) node.properties = null;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
if (node instanceof AST_Sequence) {
|
if (node instanceof AST_Sequence) {
|
||||||
@@ -7603,11 +7608,22 @@ merge(Compressor.prototype, {
|
|||||||
node.body = body;
|
node.body = body;
|
||||||
}
|
}
|
||||||
} else if (body instanceof AST_Sequence) {
|
} else if (body instanceof AST_Sequence) {
|
||||||
var tail = body.tail_node();
|
var exprs = body.expressions;
|
||||||
if (tail instanceof AST_Await && is_primitive(compressor, tail.expression)) {
|
for (var i = exprs.length; --i >= 0;) {
|
||||||
tail = tail.expression.drop_side_effect_free(compressor);
|
var tail = exprs[i];
|
||||||
body.expressions.pop();
|
if (!(tail instanceof AST_Await)) break;
|
||||||
if (tail) body.expressions.push(tail);
|
if (!is_primitive(compressor, tail.expression)) break;
|
||||||
|
if (exprs[i] = tail.expression.drop_side_effect_free(compressor)) break;
|
||||||
|
}
|
||||||
|
switch (i) {
|
||||||
|
case -1:
|
||||||
|
return make_node(AST_EmptyStatement, node);
|
||||||
|
case 0:
|
||||||
|
node.body = exprs[0];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
exprs.length = i + 1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
@@ -7691,24 +7707,24 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
def(AST_Class, function(compressor, first_in_statement) {
|
function drop_class(self, compressor, first_in_statement) {
|
||||||
var exprs = [], values = [];
|
var exprs = [], values = [];
|
||||||
var props = this.properties;
|
var props = self.properties;
|
||||||
for (var i = 0; i < props.length; i++) {
|
for (var i = 0; i < props.length; i++) {
|
||||||
var prop = props[i];
|
var prop = props[i];
|
||||||
if (prop.key instanceof AST_Node) exprs.push(prop.key);
|
if (prop.key instanceof AST_Node) exprs.push(prop.key);
|
||||||
if (prop.static && prop.value
|
if (prop.static && prop.value
|
||||||
&& prop instanceof AST_ClassField
|
&& prop instanceof AST_ClassField
|
||||||
&& prop.value.has_side_effects(compressor)) {
|
&& prop.value.has_side_effects(compressor)) {
|
||||||
if (prop.value.contains_this()) return this;
|
if (prop.value.contains_this()) return self;
|
||||||
values.push(prop.value);
|
values.push(prop.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var base = this.extends;
|
var base = self.extends;
|
||||||
if (base) {
|
if (base) {
|
||||||
if (base instanceof AST_SymbolRef) base = base.fixed_value();
|
if (base instanceof AST_SymbolRef) base = base.fixed_value();
|
||||||
base = !safe_for_extends(base);
|
base = !safe_for_extends(base);
|
||||||
if (!base) exprs.unshift(this.extends);
|
if (!base) exprs.unshift(self.extends);
|
||||||
}
|
}
|
||||||
exprs = trim(exprs, compressor, first_in_statement);
|
exprs = trim(exprs, compressor, first_in_statement);
|
||||||
if (exprs) first_in_statement = false;
|
if (exprs) first_in_statement = false;
|
||||||
@@ -7718,26 +7734,32 @@ merge(Compressor.prototype, {
|
|||||||
exprs = [];
|
exprs = [];
|
||||||
}
|
}
|
||||||
if (base) {
|
if (base) {
|
||||||
var node = to_class_expr(this, true);
|
var node = to_class_expr(self, true);
|
||||||
node.properties = [];
|
node.properties = [];
|
||||||
if (exprs.length) node.properties.push(make_node(AST_ClassMethod, this, {
|
if (exprs.length) node.properties.push(make_node(AST_ClassMethod, self, {
|
||||||
key: make_sequence(this, exprs),
|
key: make_sequence(self, exprs),
|
||||||
value: make_node(AST_Function, this, {
|
value: make_node(AST_Function, self, {
|
||||||
argnames: [],
|
argnames: [],
|
||||||
body: [],
|
body: [],
|
||||||
}).init_vars(node),
|
}).init_vars(node),
|
||||||
}));
|
}));
|
||||||
exprs = [ node ];
|
exprs = [ node ];
|
||||||
}
|
}
|
||||||
if (values) exprs.push(make_node(AST_Call, this, {
|
if (values) exprs.push(make_node(AST_Call, self, {
|
||||||
expression: make_node(AST_Arrow, this, {
|
expression: make_node(AST_Arrow, self, {
|
||||||
argnames: [],
|
argnames: [],
|
||||||
body: [],
|
body: [],
|
||||||
value: make_sequence(this, values),
|
value: make_sequence(self, values),
|
||||||
}).init_vars(this.parent_scope),
|
}).init_vars(self.parent_scope),
|
||||||
args: [],
|
args: [],
|
||||||
}));
|
}));
|
||||||
return make_sequence(this, exprs);
|
return make_sequence(self, exprs);
|
||||||
|
}
|
||||||
|
def(AST_ClassExpression, function(compressor, first_in_statement) {
|
||||||
|
var self = this;
|
||||||
|
var name = self.name;
|
||||||
|
if (name && name.fixed_value() !== self && name.definition().references.length > 0) return self;
|
||||||
|
return drop_class(self, compressor, first_in_statement);
|
||||||
});
|
});
|
||||||
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);
|
||||||
@@ -7778,6 +7800,9 @@ merge(Compressor.prototype, {
|
|||||||
return exprs.length == 0 ? null : make_sequence(this, exprs);
|
return exprs.length == 0 ? null : make_sequence(this, exprs);
|
||||||
});
|
});
|
||||||
def(AST_Constant, return_null);
|
def(AST_Constant, return_null);
|
||||||
|
def(AST_DefClass, function(compressor, first_in_statement) {
|
||||||
|
return drop_class(this, compressor, first_in_statement);
|
||||||
|
});
|
||||||
def(AST_Dot, function(compressor, first_in_statement) {
|
def(AST_Dot, function(compressor, first_in_statement) {
|
||||||
var expr = this.expression;
|
var expr = this.expression;
|
||||||
if (!this.optional && expr.may_throw_on_access(compressor)) return this;
|
if (!this.optional && expr.may_throw_on_access(compressor)) return this;
|
||||||
@@ -8104,10 +8129,6 @@ merge(Compressor.prototype, {
|
|||||||
cond = self.condition.is_truthy() || self.condition.evaluate(compressor, true);
|
cond = self.condition.is_truthy() || self.condition.evaluate(compressor, true);
|
||||||
} else if (cond) {
|
} else if (cond) {
|
||||||
self.condition = null;
|
self.condition = null;
|
||||||
} else if (!compressor.option("dead_code")) {
|
|
||||||
var orig = self.condition;
|
|
||||||
self.condition = make_node_from_constant(cond, self.condition);
|
|
||||||
self.condition = best_of_expression(self.condition.transform(compressor), orig);
|
|
||||||
}
|
}
|
||||||
if (!cond) {
|
if (!cond) {
|
||||||
if (compressor.option("dead_code")) {
|
if (compressor.option("dead_code")) {
|
||||||
@@ -8214,40 +8235,88 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fuzzy_eval(compressor, node, nullish) {
|
||||||
|
if (node.truthy) return true;
|
||||||
|
if (node.falsy && !nullish) return false;
|
||||||
|
if (node.is_truthy()) return true;
|
||||||
|
return node.evaluate(compressor, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mark_duplicate_condition(compressor, node) {
|
||||||
|
for (var level = 0, child = compressor.self(), parent; ; child = parent) {
|
||||||
|
parent = compressor.parent(level++);
|
||||||
|
if (parent instanceof AST_Binary) {
|
||||||
|
var op = parent.operator;
|
||||||
|
if (!lazy_op[op]) return;
|
||||||
|
var left = parent.left;
|
||||||
|
if (left === child) continue;
|
||||||
|
if (node.equivalent_to(left)) node[op == "&&" ? "truthy" : "falsy"] = true;
|
||||||
|
} else if (parent instanceof AST_Conditional) {
|
||||||
|
var cond = parent.condition;
|
||||||
|
if (cond === child) continue;
|
||||||
|
if (node.equivalent_to(cond)) switch (child) {
|
||||||
|
case parent.consequent:
|
||||||
|
node.truthy = true;
|
||||||
|
break;
|
||||||
|
case parent.alternative:
|
||||||
|
node.falsy = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (parent instanceof AST_Exit) {
|
||||||
|
break;
|
||||||
|
} else if (parent instanceof AST_If) {
|
||||||
|
break;
|
||||||
|
} else if (parent instanceof AST_Sequence) {
|
||||||
|
if (parent.expressions[0] === child) continue;
|
||||||
|
} else if (parent instanceof AST_SimpleStatement) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (true) {
|
||||||
|
child = parent;
|
||||||
|
parent = compressor.parent(level++);
|
||||||
|
if (parent instanceof AST_BlockStatement) {
|
||||||
|
if (parent.body[0] === child) continue;
|
||||||
|
} else if (parent instanceof AST_If) {
|
||||||
|
var cond = parent.condition;
|
||||||
|
if (cond === child) continue;
|
||||||
|
if (node.equivalent_to(cond)) switch (child) {
|
||||||
|
case parent.body:
|
||||||
|
node.truthy = true;
|
||||||
|
break;
|
||||||
|
case parent.alternative:
|
||||||
|
node.falsy = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OPT(AST_If, function(self, compressor) {
|
OPT(AST_If, function(self, compressor) {
|
||||||
if (is_empty(self.alternative)) self.alternative = null;
|
if (is_empty(self.alternative)) self.alternative = null;
|
||||||
|
|
||||||
if (!compressor.option("conditionals")) return self;
|
if (!compressor.option("conditionals")) return self;
|
||||||
|
if (compressor.option("booleans") && !self.condition.has_side_effects(compressor)) {
|
||||||
|
mark_duplicate_condition(compressor, self.condition);
|
||||||
|
}
|
||||||
// if condition can be statically determined, warn and drop
|
// if condition can be statically determined, warn and drop
|
||||||
// one of the blocks. note, statically determined implies
|
// one of the blocks. note, statically determined implies
|
||||||
// “has no side effects”; also it doesn't work for cases like
|
// “has no side effects”; also it doesn't work for cases like
|
||||||
// `x && true`, though it probably should.
|
// `x && true`, though it probably should.
|
||||||
var cond = self.condition.evaluate(compressor);
|
|
||||||
if (!compressor.option("dead_code") && !(cond instanceof AST_Node)) {
|
|
||||||
var orig = self.condition;
|
|
||||||
self.condition = make_node_from_constant(cond, orig);
|
|
||||||
self.condition = best_of_expression(self.condition.transform(compressor), orig);
|
|
||||||
}
|
|
||||||
if (compressor.option("dead_code")) {
|
if (compressor.option("dead_code")) {
|
||||||
if (cond instanceof AST_Node) {
|
var cond = fuzzy_eval(compressor, self.condition);
|
||||||
cond = self.condition.is_truthy() || self.condition.evaluate(compressor, true);
|
|
||||||
}
|
|
||||||
if (!cond) {
|
if (!cond) {
|
||||||
AST_Node.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
|
AST_Node.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
|
||||||
var body = [
|
var body = [ make_node(AST_SimpleStatement, self.condition, { body: self.condition }) ];
|
||||||
make_node(AST_SimpleStatement, self.condition, {
|
|
||||||
body: self.condition
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
extract_declarations_from_unreachable_code(compressor, self.body, body);
|
extract_declarations_from_unreachable_code(compressor, self.body, body);
|
||||||
if (self.alternative) body.push(self.alternative);
|
if (self.alternative) body.push(self.alternative);
|
||||||
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
|
return make_node(AST_BlockStatement, self, { body: body }).optimize(compressor);
|
||||||
} else if (!(cond instanceof AST_Node)) {
|
} else if (!(cond instanceof AST_Node)) {
|
||||||
AST_Node.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
|
AST_Node.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
|
||||||
var body = [
|
var body = [
|
||||||
make_node(AST_SimpleStatement, self.condition, {
|
make_node(AST_SimpleStatement, self.condition, { body: self.condition }),
|
||||||
body: self.condition
|
|
||||||
}),
|
|
||||||
self.body,
|
self.body,
|
||||||
];
|
];
|
||||||
if (self.alternative) extract_declarations_from_unreachable_code(compressor, self.alternative, body);
|
if (self.alternative) extract_declarations_from_unreachable_code(compressor, self.alternative, body);
|
||||||
@@ -8271,9 +8340,7 @@ merge(Compressor.prototype, {
|
|||||||
var body_exprs = sequencesize(self.body, body, var_defs, refs);
|
var body_exprs = sequencesize(self.body, body, var_defs, refs);
|
||||||
var alt_exprs = sequencesize(self.alternative, body, var_defs, refs);
|
var alt_exprs = sequencesize(self.alternative, body, var_defs, refs);
|
||||||
if (body_exprs && alt_exprs) {
|
if (body_exprs && alt_exprs) {
|
||||||
if (var_defs.length > 0) body.push(make_node(AST_Var, self, {
|
if (var_defs.length > 0) body.push(make_node(AST_Var, self, { definitions: var_defs }));
|
||||||
definitions: var_defs
|
|
||||||
}));
|
|
||||||
if (body_exprs.length == 0) {
|
if (body_exprs.length == 0) {
|
||||||
body.push(make_node(AST_SimpleStatement, self.condition, {
|
body.push(make_node(AST_SimpleStatement, self.condition, {
|
||||||
body: alt_exprs.length > 0 ? make_node(AST_Binary, self, {
|
body: alt_exprs.length > 0 ? make_node(AST_Binary, self, {
|
||||||
@@ -8420,22 +8487,14 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
OPT(AST_Switch, function(self, compressor) {
|
OPT(AST_Switch, function(self, compressor) {
|
||||||
if (!compressor.option("switches")) return self;
|
if (!compressor.option("switches")) return self;
|
||||||
var branch;
|
|
||||||
var value = self.expression.evaluate(compressor);
|
|
||||||
if (!(value instanceof AST_Node)) {
|
|
||||||
var orig = self.expression;
|
|
||||||
self.expression = make_node_from_constant(value, orig);
|
|
||||||
self.expression = best_of_expression(self.expression.transform(compressor), orig);
|
|
||||||
}
|
|
||||||
if (!compressor.option("dead_code")) return self;
|
if (!compressor.option("dead_code")) return self;
|
||||||
if (value instanceof AST_Node) {
|
|
||||||
value = self.expression.evaluate(compressor, true);
|
|
||||||
}
|
|
||||||
var decl = [];
|
|
||||||
var body = [];
|
var body = [];
|
||||||
|
var branch;
|
||||||
|
var decl = [];
|
||||||
var default_branch;
|
var default_branch;
|
||||||
var exact_match;
|
var exact_match;
|
||||||
for (var i = 0, len = self.body.length; i < len && !exact_match; i++) {
|
var side_effects = [];
|
||||||
|
for (var i = 0, len = self.body.length; i < len; i++) {
|
||||||
branch = self.body[i];
|
branch = self.body[i];
|
||||||
if (branch instanceof AST_Default) {
|
if (branch instanceof AST_Default) {
|
||||||
var prev = body[body.length - 1];
|
var prev = body[body.length - 1];
|
||||||
@@ -8445,33 +8504,61 @@ merge(Compressor.prototype, {
|
|||||||
} else {
|
} else {
|
||||||
default_branch = branch;
|
default_branch = branch;
|
||||||
}
|
}
|
||||||
} else if (!(value instanceof AST_Node)) {
|
} else {
|
||||||
var exp = branch.expression.evaluate(compressor);
|
var exp = branch.expression;
|
||||||
if (!(exp instanceof AST_Node) && exp !== value) {
|
var equals = make_node(AST_Binary, self, {
|
||||||
|
operator: "===",
|
||||||
|
left: self.expression,
|
||||||
|
right: exp,
|
||||||
|
}).evaluate(compressor, true);
|
||||||
|
if (!equals) {
|
||||||
|
if (exp.has_side_effects(compressor)) side_effects.push(exp);
|
||||||
eliminate_branch(branch, body[body.length - 1]);
|
eliminate_branch(branch, body[body.length - 1]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (exp instanceof AST_Node) exp = branch.expression.evaluate(compressor, true);
|
if (!(equals instanceof AST_Node)) {
|
||||||
if (exp === value) {
|
|
||||||
exact_match = branch;
|
|
||||||
if (default_branch) {
|
if (default_branch) {
|
||||||
var default_index = body.indexOf(default_branch);
|
var default_index = body.indexOf(default_branch);
|
||||||
body.splice(default_index, 1);
|
body.splice(default_index, 1);
|
||||||
eliminate_branch(default_branch, body[default_index - 1]);
|
eliminate_branch(default_branch, body[default_index - 1]);
|
||||||
default_branch = null;
|
default_branch = null;
|
||||||
}
|
}
|
||||||
|
if (exp.has_side_effects(compressor)) {
|
||||||
|
exact_match = branch;
|
||||||
|
} else {
|
||||||
|
default_branch = branch = make_node(AST_Default, branch, branch);
|
||||||
|
}
|
||||||
|
while (++i < len) eliminate_branch(self.body[i], branch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (aborts(branch)) {
|
if (i + 1 >= len || aborts(branch)) {
|
||||||
var prev = body[body.length - 1];
|
var prev = body[body.length - 1];
|
||||||
if (aborts(prev) && prev.body.length == branch.body.length
|
var statements = branch.body;
|
||||||
&& make_node(AST_BlockStatement, prev, prev).equivalent_to(make_node(AST_BlockStatement, branch, branch))) {
|
if (aborts(prev)) switch (prev.body.length - statements.length) {
|
||||||
prev.body = [];
|
case 1:
|
||||||
|
var stat = prev.body[prev.body.length - 1];
|
||||||
|
if (!is_break(stat, compressor)) break;
|
||||||
|
statements = statements.concat(stat);
|
||||||
|
case 0:
|
||||||
|
var prev_block = make_node(AST_BlockStatement, prev, prev);
|
||||||
|
var next_block = make_node(AST_BlockStatement, branch, { body: statements });
|
||||||
|
if (prev_block.equivalent_to(next_block)) prev.body = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (side_effects.length) {
|
||||||
|
if (branch instanceof AST_Default) {
|
||||||
|
body.push(make_node(AST_Case, self, { expression: make_sequence(self, side_effects), body: [] }));
|
||||||
|
} else {
|
||||||
|
side_effects.push(branch.expression);
|
||||||
|
branch.expression = make_sequence(self, side_effects);
|
||||||
|
}
|
||||||
|
side_effects = [];
|
||||||
|
}
|
||||||
body.push(branch);
|
body.push(branch);
|
||||||
}
|
}
|
||||||
while (i < len) eliminate_branch(self.body[i++], body[body.length - 1]);
|
if (side_effects.length && !exact_match) {
|
||||||
|
body.push(make_node(AST_Case, self, { expression: make_sequence(self, side_effects), body: [] }));
|
||||||
|
}
|
||||||
while (branch = body[body.length - 1]) {
|
while (branch = body[body.length - 1]) {
|
||||||
var stat = branch.body[branch.body.length - 1];
|
var stat = branch.body[branch.body.length - 1];
|
||||||
if (is_break(stat, compressor)) branch.body.pop();
|
if (is_break(stat, compressor)) branch.body.pop();
|
||||||
@@ -8488,12 +8575,24 @@ merge(Compressor.prototype, {
|
|||||||
eliminate_branch(branch);
|
eliminate_branch(branch);
|
||||||
if (body.pop() === default_branch) default_branch = null;
|
if (body.pop() === default_branch) default_branch = null;
|
||||||
}
|
}
|
||||||
if (body.length == 0) {
|
if (!branch) {
|
||||||
return make_node(AST_BlockStatement, self, {
|
decl.push(make_node(AST_SimpleStatement, self.expression, { body: self.expression }));
|
||||||
body: decl.concat(make_node(AST_SimpleStatement, self.expression, {
|
if (side_effects.length) decl.push(make_node(AST_SimpleStatement, self, {
|
||||||
body: self.expression
|
body: make_sequence(self, side_effects),
|
||||||
}))
|
}));
|
||||||
}).optimize(compressor);
|
return make_node(AST_BlockStatement, self, { body: decl }).optimize(compressor);
|
||||||
|
}
|
||||||
|
if (branch === default_branch) while (branch = body[body.length - 2]) {
|
||||||
|
if (branch instanceof AST_Default) break;
|
||||||
|
if (!has_declarations_only(branch)) break;
|
||||||
|
var exp = branch.expression;
|
||||||
|
if (exp.has_side_effects(compressor)) {
|
||||||
|
var prev = body[body.length - 3];
|
||||||
|
if (prev && !aborts(prev)) break;
|
||||||
|
default_branch.body.unshift(make_node(AST_SimpleStatement, self, { body: exp }));
|
||||||
|
}
|
||||||
|
eliminate_branch(branch);
|
||||||
|
body.splice(-2, 1);
|
||||||
}
|
}
|
||||||
body[0].body = decl.concat(body[0].body);
|
body[0].body = decl.concat(body[0].body);
|
||||||
self.body = body;
|
self.body = body;
|
||||||
@@ -9774,7 +9873,7 @@ merge(Compressor.prototype, {
|
|||||||
OPT(AST_Sequence, function(self, compressor) {
|
OPT(AST_Sequence, function(self, compressor) {
|
||||||
var expressions = filter_for_side_effects();
|
var expressions = filter_for_side_effects();
|
||||||
var end = expressions.length - 1;
|
var end = expressions.length - 1;
|
||||||
merge_conditional_assignments();
|
merge_assignments();
|
||||||
trim_right_for_undefined();
|
trim_right_for_undefined();
|
||||||
if (end == 0) {
|
if (end == 0) {
|
||||||
self = maintain_this_binding(compressor, compressor.parent(), compressor.self(), expressions[0]);
|
self = maintain_this_binding(compressor, compressor.parent(), compressor.self(), expressions[0]);
|
||||||
@@ -9811,19 +9910,33 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function merge_conditional_assignments() {
|
function is_simple_assign(node) {
|
||||||
if (!compressor.option("conditionals")) return;
|
return node instanceof AST_Assign
|
||||||
|
&& node.operator == "="
|
||||||
|
&& node.left instanceof AST_SymbolRef
|
||||||
|
&& node.left.definition();
|
||||||
|
}
|
||||||
|
|
||||||
|
function merge_assignments() {
|
||||||
for (var i = 1; i < end; i++) {
|
for (var i = 1; i < end; i++) {
|
||||||
var assign = expressions[i - 1];
|
var prev = expressions[i - 1];
|
||||||
if (!(assign instanceof AST_Assign)) continue;
|
var def = is_simple_assign(prev);
|
||||||
if (assign.operator != "=") continue;
|
if (!def) continue;
|
||||||
if (!(assign.left instanceof AST_SymbolRef)) continue;
|
var expr = expressions[i];
|
||||||
var def = assign.left.definition();
|
if (compressor.option("conditionals")) {
|
||||||
var cond = to_conditional_assignment(compressor, def, assign.right, expressions[i]);
|
var cond = to_conditional_assignment(compressor, def, prev.right, expr);
|
||||||
if (!cond) continue;
|
if (cond) {
|
||||||
assign.right = cond;
|
prev.right = cond;
|
||||||
expressions.splice(i, 1);
|
expressions.splice(i--, 1);
|
||||||
end--;
|
end--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (compressor.option("dead_code")
|
||||||
|
&& is_simple_assign(expr) === def
|
||||||
|
&& expr.right.is_constant_expression(def.scope.resolve())) {
|
||||||
|
expressions[--i] = prev.right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -10185,7 +10298,18 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var in_bool = compressor.option("booleans") && compressor.in_boolean_context();
|
var in_bool = false;
|
||||||
|
var parent = compressor.parent();
|
||||||
|
if (compressor.option("booleans")) {
|
||||||
|
var lhs = self.left;
|
||||||
|
if (lazy_op[self.operator] && !lhs.has_side_effects(compressor)) {
|
||||||
|
if (lhs.equivalent_to(self.right)) {
|
||||||
|
return maintain_this_binding(compressor, parent, compressor.self(), lhs).optimize(compressor);
|
||||||
|
}
|
||||||
|
mark_duplicate_condition(compressor, lhs);
|
||||||
|
}
|
||||||
|
in_bool = compressor.in_boolean_context();
|
||||||
|
}
|
||||||
if (in_bool) switch (self.operator) {
|
if (in_bool) switch (self.operator) {
|
||||||
case "+":
|
case "+":
|
||||||
var ll = self.left.evaluate(compressor);
|
var ll = self.left.evaluate(compressor);
|
||||||
@@ -10219,7 +10343,6 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var parent = compressor.parent();
|
|
||||||
if (compressor.option("comparisons") && self.is_boolean(compressor)) {
|
if (compressor.option("comparisons") && self.is_boolean(compressor)) {
|
||||||
if (!(parent instanceof AST_Binary) || parent instanceof AST_Assign) {
|
if (!(parent instanceof AST_Binary) || parent instanceof AST_Assign) {
|
||||||
var negated = best_of(compressor, self, make_node(AST_UnaryPrefix, self, {
|
var negated = best_of(compressor, self, make_node(AST_UnaryPrefix, self, {
|
||||||
@@ -10277,7 +10400,7 @@ merge(Compressor.prototype, {
|
|||||||
var associative = true;
|
var associative = true;
|
||||||
switch (self.operator) {
|
switch (self.operator) {
|
||||||
case "&&":
|
case "&&":
|
||||||
var ll = fuzzy_eval(self.left);
|
var ll = fuzzy_eval(compressor, self.left);
|
||||||
if (!ll) {
|
if (!ll) {
|
||||||
AST_Node.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
AST_Node.warn("Condition left of && always false [{file}:{line},{col}]", self.start);
|
||||||
return maintain_this_binding(compressor, parent, compressor.self(), self.left).optimize(compressor);
|
return maintain_this_binding(compressor, parent, compressor.self(), self.left).optimize(compressor);
|
||||||
@@ -10313,7 +10436,7 @@ merge(Compressor.prototype, {
|
|||||||
case "??":
|
case "??":
|
||||||
var nullish = true;
|
var nullish = true;
|
||||||
case "||":
|
case "||":
|
||||||
var ll = fuzzy_eval(self.left, nullish);
|
var ll = fuzzy_eval(compressor, self.left, nullish);
|
||||||
if (nullish ? ll == null : !ll) {
|
if (nullish ? ll == null : !ll) {
|
||||||
AST_Node.warn("Condition left of {operator} always {value} [{file}:{line},{col}]", {
|
AST_Node.warn("Condition left of {operator} always {value} [{file}:{line},{col}]", {
|
||||||
operator: self.operator,
|
operator: self.operator,
|
||||||
@@ -10696,13 +10819,6 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function fuzzy_eval(node, nullish) {
|
|
||||||
if (node.truthy) return true;
|
|
||||||
if (node.falsy && !nullish) return false;
|
|
||||||
if (node.is_truthy()) return true;
|
|
||||||
return node.evaluate(compressor, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
function is_indexFn(node) {
|
function is_indexFn(node) {
|
||||||
return node.TYPE == "Call"
|
return node.TYPE == "Call"
|
||||||
&& node.expression instanceof AST_Dot
|
&& node.expression instanceof AST_Dot
|
||||||
@@ -11055,9 +11171,11 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
var scan_scope = new TreeWalker(function(node) {
|
var scan_scope = new TreeWalker(function(node) {
|
||||||
if (reachable) return true;
|
if (reachable) return true;
|
||||||
if (node instanceof AST_Scope && node !== self) {
|
if (node instanceof AST_Lambda && node !== self) {
|
||||||
var parent = scan_scope.parent();
|
if (!(node.name || is_async(node) || is_generator(node))) {
|
||||||
if (parent instanceof AST_Call && parent.expression === node) return;
|
var parent = scan_scope.parent();
|
||||||
|
if (parent instanceof AST_Call && parent.expression === node) return;
|
||||||
|
}
|
||||||
node.walk(find_ref);
|
node.walk(find_ref);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -11113,28 +11231,36 @@ merge(Compressor.prototype, {
|
|||||||
if (node instanceof AST_PropAccess) return true;
|
if (node instanceof AST_PropAccess) return true;
|
||||||
if (!found && node instanceof AST_SymbolRef && node.definition() === def) {
|
if (!found && node instanceof AST_SymbolRef && node.definition() === def) {
|
||||||
if (in_try(level, parent)) return true;
|
if (in_try(level, parent)) return true;
|
||||||
def.fixed = false;
|
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
})) break;
|
})) break;
|
||||||
if (found) return strip_assignment();
|
if (!found) continue;
|
||||||
} else if (parent instanceof AST_Exit) {
|
return strip_assignment(def);
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_Exit) {
|
||||||
if (!local) break;
|
if (!local) break;
|
||||||
if (in_try(level, parent)) break;
|
if (in_try(level, parent)) break;
|
||||||
if (is_reachable(scope, [ def ])) break;
|
if (is_reachable(scope, [ def ])) break;
|
||||||
def.fixed = false;
|
return strip_assignment(def);
|
||||||
return strip_assignment();
|
}
|
||||||
} else if (parent instanceof AST_VarDef) {
|
if (parent instanceof AST_SimpleStatement) {
|
||||||
|
if (!local) break;
|
||||||
|
if (is_reachable(scope, [ def ])) break;
|
||||||
|
var stat;
|
||||||
|
do {
|
||||||
|
stat = parent;
|
||||||
|
parent = compressor.parent(level++);
|
||||||
|
if (parent === scope && is_last_statement(parent.body, stat)) return strip_assignment(def);
|
||||||
|
} while (is_tail_block(stat, parent));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_VarDef) {
|
||||||
if (!(parent.name instanceof AST_SymbolDeclaration)) continue;
|
if (!(parent.name instanceof AST_SymbolDeclaration)) continue;
|
||||||
if (parent.name.definition() !== def) continue;
|
if (parent.name.definition() !== def) continue;
|
||||||
if (in_try(level, parent)) break;
|
if (in_try(level, parent)) break;
|
||||||
def.fixed = false;
|
return strip_assignment(def);
|
||||||
return strip_assignment();
|
|
||||||
}
|
}
|
||||||
} while (parent instanceof AST_Binary && parent.right === node
|
} while (is_tail(node, parent));
|
||||||
|| parent instanceof AST_Conditional && parent.condition !== node
|
|
||||||
|| parent instanceof AST_Sequence && parent.tail_node() === node
|
|
||||||
|| parent instanceof AST_UnaryPrefix);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (compressor.option("sequences")) {
|
if (compressor.option("sequences")) {
|
||||||
@@ -11179,26 +11305,55 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return try_evaluate(compressor, self);
|
return try_evaluate(compressor, self);
|
||||||
|
|
||||||
|
function is_tail(node, parent) {
|
||||||
|
if (parent instanceof AST_Binary) {
|
||||||
|
return parent.right === node || parent.right.is_constant_expression(scope);
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_Conditional) {
|
||||||
|
return parent.condition !== node
|
||||||
|
|| parent.consequent.is_constant_expression(scope)
|
||||||
|
&& parent.alternative.is_constant_expression(scope);
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_Sequence) {
|
||||||
|
var exprs = parent.expressions;
|
||||||
|
var stop = exprs.indexOf(node);
|
||||||
|
if (stop < 0) return false;
|
||||||
|
for (var i = exprs.length; --i > stop;) {
|
||||||
|
if (!exprs[i].is_constant_expression(scope)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (parent instanceof AST_UnaryPrefix) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_tail_block(stat, parent) {
|
||||||
|
if (parent instanceof AST_BlockStatement) return is_last_statement(parent.body, stat);
|
||||||
|
if (parent instanceof AST_Catch) return is_last_statement(parent.body, stat);
|
||||||
|
if (parent instanceof AST_Finally) return is_last_statement(parent.body, stat);
|
||||||
|
if (parent instanceof AST_If) return parent.body === stat || parent.alternative === stat;
|
||||||
|
if (parent instanceof AST_Try) return parent.bfinally ? parent.bfinally === stat : parent.bcatch === stat;
|
||||||
|
}
|
||||||
|
|
||||||
function in_try(level, node) {
|
function in_try(level, node) {
|
||||||
var right = self.right;
|
var right = self.right;
|
||||||
self.right = make_node(AST_Null, right);
|
self.right = make_node(AST_Null, right);
|
||||||
var may_throw = node.may_throw(compressor);
|
var may_throw = node.may_throw(compressor);
|
||||||
self.right = right;
|
self.right = right;
|
||||||
var parent;
|
for (var parent; parent = compressor.parent(level++); node = parent) {
|
||||||
while (parent = compressor.parent(level++)) {
|
|
||||||
if (parent === scope) return false;
|
if (parent === scope) return false;
|
||||||
if (parent instanceof AST_Try) {
|
if (parent instanceof AST_Try) {
|
||||||
if (parent.bfinally) return true;
|
if (parent.bfinally && parent.bfinally !== node) return true;
|
||||||
if (may_throw && parent.bcatch) return true;
|
if (may_throw && parent.bcatch && parent.bcatch !== node) return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function strip_assignment() {
|
function strip_assignment(def) {
|
||||||
|
if (def) def.fixed = false;
|
||||||
return (self.operator != "=" ? make_node(AST_Binary, self, {
|
return (self.operator != "=" ? make_node(AST_Binary, self, {
|
||||||
operator: self.operator.slice(0, -1),
|
operator: self.operator.slice(0, -1),
|
||||||
left: self.left,
|
left: self.left,
|
||||||
right: self.right
|
right: self.right,
|
||||||
}) : maintain_this_binding(compressor, compressor.parent(), self, self.right)).optimize(compressor);
|
}) : maintain_this_binding(compressor, compressor.parent(), self, self.right)).optimize(compressor);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -11211,7 +11366,11 @@ merge(Compressor.prototype, {
|
|||||||
return make_sequence(self, expressions);
|
return make_sequence(self, expressions);
|
||||||
}
|
}
|
||||||
if (!compressor.option("conditionals")) return self;
|
if (!compressor.option("conditionals")) return self;
|
||||||
var condition = self.condition.is_truthy() || self.condition.evaluate(compressor, true);
|
var condition = self.condition;
|
||||||
|
if (compressor.option("booleans") && !condition.has_side_effects(compressor)) {
|
||||||
|
mark_duplicate_condition(compressor, condition);
|
||||||
|
}
|
||||||
|
condition = fuzzy_eval(compressor, condition);
|
||||||
if (!condition) {
|
if (!condition) {
|
||||||
AST_Node.warn("Condition always false [{file}:{line},{col}]", self.start);
|
AST_Node.warn("Condition always false [{file}:{line},{col}]", self.start);
|
||||||
return make_sequence(self, [ self.condition, self.alternative ]).optimize(compressor);
|
return make_sequence(self, [ self.condition, self.alternative ]).optimize(compressor);
|
||||||
@@ -11675,7 +11834,11 @@ merge(Compressor.prototype, {
|
|||||||
} else if (compressor.has_directive("use strict")
|
} else if (compressor.has_directive("use strict")
|
||||||
|| fn.name
|
|| fn.name
|
||||||
|| fn.rest
|
|| fn.rest
|
||||||
|| !(fn_parent instanceof AST_Call && index < fn_parent.args.length)
|
|| !(fn_parent instanceof AST_Call
|
||||||
|
&& index < fn_parent.args.length
|
||||||
|
&& all(fn_parent.args.slice(0, index + 1), function(arg) {
|
||||||
|
return !(arg instanceof AST_Spread);
|
||||||
|
}))
|
||||||
|| !all(fn.argnames, function(argname) {
|
|| !all(fn.argnames, function(argname) {
|
||||||
return argname instanceof AST_SymbolFunarg;
|
return argname instanceof AST_SymbolFunarg;
|
||||||
})) {
|
})) {
|
||||||
@@ -11816,7 +11979,7 @@ merge(Compressor.prototype, {
|
|||||||
var props = expr.properties;
|
var props = expr.properties;
|
||||||
for (var i = props.length; --i >= 0;) {
|
for (var i = props.length; --i >= 0;) {
|
||||||
var prop = props[i];
|
var prop = props[i];
|
||||||
if (prop.key != key) continue;
|
if (prop.key !== key) continue;
|
||||||
if (!all(props, can_hoist_property)) break;
|
if (!all(props, can_hoist_property)) break;
|
||||||
if (!safe_to_flatten(prop.value, compressor)) break;
|
if (!safe_to_flatten(prop.value, compressor)) break;
|
||||||
props = props.map(function(prop) {
|
props = props.map(function(prop) {
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ function minify(files, options) {
|
|||||||
if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle" ]);
|
||||||
if (options.toplevel) set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
if (options.toplevel) set_shorthand("toplevel", options, [ "compress", "mangle" ]);
|
||||||
if (options.v8) set_shorthand("v8", options, [ "mangle", "output" ]);
|
if (options.v8) set_shorthand("v8", options, [ "mangle", "output" ]);
|
||||||
if (options.webkit) set_shorthand("webkit", options, [ "mangle", "output" ]);
|
if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output" ]);
|
||||||
var quoted_props;
|
var quoted_props;
|
||||||
if (options.mangle) {
|
if (options.mangle) {
|
||||||
options.mangle = defaults(options.mangle, {
|
options.mangle = defaults(options.mangle, {
|
||||||
|
|||||||
@@ -1134,58 +1134,54 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function map(moztype, mytype, propmap) {
|
function map(moztype, mytype, propmap) {
|
||||||
var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
|
var moz_to_me = [
|
||||||
moz_to_me += "return new U2." + mytype.name + "({\n" +
|
"start: my_start_token(M)",
|
||||||
"start: my_start_token(M),\n" +
|
"end: my_end_token(M)",
|
||||||
"end: my_end_token(M)";
|
];
|
||||||
|
var me_to_moz = [
|
||||||
var me_to_moz = "function To_Moz_" + moztype + "(M){\n";
|
"type: " + JSON.stringify(moztype),
|
||||||
me_to_moz += "return {\n" +
|
];
|
||||||
"type: " + JSON.stringify(moztype);
|
|
||||||
|
|
||||||
if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop) {
|
if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop) {
|
||||||
var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
|
var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
|
||||||
if (!m) throw new Error("Can't understand property map: " + prop);
|
if (!m) throw new Error("Can't understand property map: " + prop);
|
||||||
var moz = m[1], how = m[2], my = m[3];
|
var moz = m[1], how = m[2], my = m[3];
|
||||||
moz_to_me += ",\n" + my + ": ";
|
|
||||||
me_to_moz += ",\n" + moz + ": ";
|
|
||||||
switch (how) {
|
switch (how) {
|
||||||
case "@":
|
case "@":
|
||||||
moz_to_me += "M." + moz + ".map(from_moz)";
|
moz_to_me.push(my + ": M." + moz + ".map(from_moz)");
|
||||||
me_to_moz += "M." + my + ".map(to_moz)";
|
me_to_moz.push(moz + ": M." + my + ".map(to_moz)");
|
||||||
break;
|
break;
|
||||||
case ">":
|
case ">":
|
||||||
moz_to_me += "from_moz(M." + moz + ")";
|
moz_to_me.push(my + ": from_moz(M." + moz + ")");
|
||||||
me_to_moz += "to_moz(M." + my + ")";
|
me_to_moz.push(moz + ": to_moz(M." + my + ")");
|
||||||
break;
|
break;
|
||||||
case "=":
|
case "=":
|
||||||
moz_to_me += "M." + moz;
|
moz_to_me.push(my + ": M." + moz);
|
||||||
me_to_moz += "M." + my;
|
me_to_moz.push(moz + ": M." + my);
|
||||||
break;
|
break;
|
||||||
case "%":
|
case "%":
|
||||||
moz_to_me += "from_moz(M." + moz + ").body";
|
moz_to_me.push(my + ": from_moz(M." + moz + ").body");
|
||||||
me_to_moz += "to_moz_block(M)";
|
me_to_moz.push(moz + ": to_moz_block(M)");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new Error("Can't understand operator in propmap: " + prop);
|
throw new Error("Can't understand operator in propmap: " + prop);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
moz_to_me += "\n})\n}";
|
MOZ_TO_ME[moztype] = new Function("U2", "my_start_token", "my_end_token", "from_moz", [
|
||||||
me_to_moz += "\n}\n}";
|
"return function From_Moz_" + moztype + "(M) {",
|
||||||
|
" return new U2.AST_" + mytype.TYPE + "({",
|
||||||
//moz_to_me = parse(moz_to_me).print_to_string({ beautify: true });
|
moz_to_me.join(",\n"),
|
||||||
//me_to_moz = parse(me_to_moz).print_to_string({ beautify: true });
|
" });",
|
||||||
//console.log(moz_to_me);
|
"};",
|
||||||
|
].join("\n"))(exports, my_start_token, my_end_token, from_moz);
|
||||||
moz_to_me = new Function("U2", "my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(
|
def_to_moz(mytype, new Function("to_moz", "to_moz_block", "to_moz_scope", [
|
||||||
exports, my_start_token, my_end_token, from_moz
|
"return function To_Moz_" + moztype + "(M) {",
|
||||||
);
|
" return {",
|
||||||
me_to_moz = new Function("to_moz", "to_moz_block", "to_moz_scope", "return(" + me_to_moz + ")")(
|
me_to_moz.join(",\n"),
|
||||||
to_moz, to_moz_block, to_moz_scope
|
" };",
|
||||||
);
|
"};",
|
||||||
MOZ_TO_ME[moztype] = moz_to_me;
|
].join("\n"))(to_moz, to_moz_block, to_moz_scope));
|
||||||
def_to_moz(mytype, me_to_moz);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var FROM_MOZ_STACK = null;
|
var FROM_MOZ_STACK = null;
|
||||||
|
|||||||
21
lib/parse.js
21
lib/parse.js
@@ -1334,21 +1334,19 @@ function parse($TEXT, options) {
|
|||||||
if (is("punc", "{")) {
|
if (is("punc", "{")) {
|
||||||
body = block_();
|
body = block_();
|
||||||
value = null;
|
value = null;
|
||||||
if (S.input.has_directive("use strict")) {
|
|
||||||
argnames.forEach(strict_verify_symbol);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
body = [];
|
body = [];
|
||||||
handle_regexp();
|
handle_regexp();
|
||||||
value = maybe_assign();
|
value = maybe_assign();
|
||||||
}
|
}
|
||||||
|
var is_strict = S.input.has_directive("use strict");
|
||||||
S.input.pop_directives_stack();
|
S.input.pop_directives_stack();
|
||||||
--S.in_function;
|
--S.in_function;
|
||||||
S.in_loop = loop;
|
S.in_loop = loop;
|
||||||
S.labels = labels;
|
S.labels = labels;
|
||||||
S.in_generator = was_gen;
|
S.in_generator = was_gen;
|
||||||
S.in_async = was_async;
|
S.in_async = was_async;
|
||||||
return new (async ? AST_AsyncArrow : AST_Arrow)({
|
var node = new (async ? AST_AsyncArrow : AST_Arrow)({
|
||||||
start: start,
|
start: start,
|
||||||
argnames: argnames,
|
argnames: argnames,
|
||||||
rest: rest,
|
rest: rest,
|
||||||
@@ -1356,6 +1354,8 @@ function parse($TEXT, options) {
|
|||||||
value: value,
|
value: value,
|
||||||
end: prev(),
|
end: prev(),
|
||||||
});
|
});
|
||||||
|
if (is_strict) node.each_argname(strict_verify_symbol);
|
||||||
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
var function_ = function(ctor) {
|
var function_ = function(ctor) {
|
||||||
@@ -1388,23 +1388,24 @@ function parse($TEXT, options) {
|
|||||||
S.in_loop = 0;
|
S.in_loop = 0;
|
||||||
S.labels = [];
|
S.labels = [];
|
||||||
var body = block_();
|
var body = block_();
|
||||||
if (S.input.has_directive("use strict")) {
|
var is_strict = S.input.has_directive("use strict");
|
||||||
if (name) strict_verify_symbol(name);
|
|
||||||
argnames.forEach(strict_verify_symbol);
|
|
||||||
if (argnames.rest) strict_verify_symbol(argnames.rest);
|
|
||||||
}
|
|
||||||
S.input.pop_directives_stack();
|
S.input.pop_directives_stack();
|
||||||
--S.in_function;
|
--S.in_function;
|
||||||
S.in_loop = loop;
|
S.in_loop = loop;
|
||||||
S.labels = labels;
|
S.labels = labels;
|
||||||
S.in_generator = was_gen;
|
S.in_generator = was_gen;
|
||||||
S.in_async = was_async;
|
S.in_async = was_async;
|
||||||
return new ctor({
|
var node = new ctor({
|
||||||
name: name,
|
name: name,
|
||||||
argnames: argnames,
|
argnames: argnames,
|
||||||
rest: argnames.rest || null,
|
rest: argnames.rest || null,
|
||||||
body: body
|
body: body
|
||||||
});
|
});
|
||||||
|
if (is_strict) {
|
||||||
|
if (name) strict_verify_symbol(name);
|
||||||
|
node.each_argname(strict_verify_symbol);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
function if_() {
|
function if_() {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
|
||||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"version": "3.13.9",
|
"version": "3.13.10",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ var urls = [
|
|||||||
"https://code.angularjs.org/1.7.8/angular.js",
|
"https://code.angularjs.org/1.7.8/angular.js",
|
||||||
"https://unpkg.com/mathjs@6.2.3/dist/math.js",
|
"https://unpkg.com/mathjs@6.2.3/dist/math.js",
|
||||||
"https://unpkg.com/react@15.3.2/dist/react.js",
|
"https://unpkg.com/react@15.3.2/dist/react.js",
|
||||||
"https://cdnjs.cloudflare.com/ajax/libs/d3/5.12.0/d3.js",
|
"https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.js",
|
||||||
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
|
"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.js",
|
||||||
"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js",
|
"https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js",
|
||||||
"https://cdnjs.cloudflare.com/ajax/libs/ember.js/2.12.2/ember.prod.js",
|
"https://cdnjs.cloudflare.com/ajax/libs/ember.js/2.12.2/ember.prod.js",
|
||||||
|
|||||||
@@ -1758,3 +1758,268 @@ issue_4987: {
|
|||||||
]
|
]
|
||||||
node_version: ">=8"
|
node_version: ">=8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5001: {
|
||||||
|
options = {
|
||||||
|
awaits: true,
|
||||||
|
inline: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 0;
|
||||||
|
(async function() {
|
||||||
|
a++ | await 42;
|
||||||
|
})();
|
||||||
|
console.log(a ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 0;
|
||||||
|
void a++;
|
||||||
|
console.log(a ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5019_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
(async function() {
|
||||||
|
await 42;
|
||||||
|
console.log(a);
|
||||||
|
})();
|
||||||
|
a = "PASS";
|
||||||
|
})("FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
(async function() {
|
||||||
|
await 42;
|
||||||
|
console.log(a);
|
||||||
|
})();
|
||||||
|
a = "PASS";
|
||||||
|
})("FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5019_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log("sync", function(a) {
|
||||||
|
(async function() {
|
||||||
|
console.log(await "async", a);
|
||||||
|
})();
|
||||||
|
return a = "PASS";
|
||||||
|
}("FAIL"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log("sync", function(a) {
|
||||||
|
(async function() {
|
||||||
|
console.log(await "async", a);
|
||||||
|
})();
|
||||||
|
return a = "PASS";
|
||||||
|
}("FAIL"));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"sync PASS",
|
||||||
|
"async PASS",
|
||||||
|
]
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5019_3: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
for (var i in "foo") {
|
||||||
|
(function(a) {
|
||||||
|
(async function() {
|
||||||
|
console.log(await "async", a);
|
||||||
|
})();
|
||||||
|
})(i);
|
||||||
|
console.log("sync", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
for (var i in "foo") {
|
||||||
|
(function(a) {
|
||||||
|
(async function() {
|
||||||
|
console.log(await "async", a);
|
||||||
|
})();
|
||||||
|
})(i);
|
||||||
|
console.log("sync", i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"sync 0",
|
||||||
|
"sync 1",
|
||||||
|
"sync 2",
|
||||||
|
"async 0",
|
||||||
|
"async 1",
|
||||||
|
"async 2",
|
||||||
|
]
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5023_1: {
|
||||||
|
options = {
|
||||||
|
awaits: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(async function() {
|
||||||
|
let a = a;
|
||||||
|
})();
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(async function() {
|
||||||
|
let a = a;
|
||||||
|
})();
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5023_2: {
|
||||||
|
options = {
|
||||||
|
awaits: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(async function() {
|
||||||
|
let a;
|
||||||
|
a = a;
|
||||||
|
})();
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
let a;
|
||||||
|
a = a;
|
||||||
|
})();
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5032_normal: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
webkit: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(value) {
|
||||||
|
console.log(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
async function f(a) {
|
||||||
|
var b = log(a), c = b;
|
||||||
|
log(b);
|
||||||
|
log(c);
|
||||||
|
}
|
||||||
|
f("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(value) {
|
||||||
|
console.log(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
async function f(c) {
|
||||||
|
var b = log(c), c = b;
|
||||||
|
log(b);
|
||||||
|
log(c);
|
||||||
|
}
|
||||||
|
f("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5032_webkit: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
webkit: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(value) {
|
||||||
|
console.log(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
async function f(a) {
|
||||||
|
var b = log(a), c = b;
|
||||||
|
log(b);
|
||||||
|
log(c);
|
||||||
|
}
|
||||||
|
f("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(value) {
|
||||||
|
console.log(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
async function f(a) {
|
||||||
|
var b = log(a), c = b;
|
||||||
|
log(b);
|
||||||
|
log(c);
|
||||||
|
}
|
||||||
|
f("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5034: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function() {
|
||||||
|
var await = function f() {
|
||||||
|
return async function() {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
await()().then(function(value) {
|
||||||
|
console.log(value === await ? "PASS" : "FAIL");
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function() {
|
||||||
|
var await = function f() {
|
||||||
|
return async function() {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
await()().then(function(value) {
|
||||||
|
console.log(value === await ? "PASS" : "FAIL");
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,6 +29,383 @@ iife_boolean_context: {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
de_morgan_1a: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
return a || a;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(42));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(42));
|
||||||
|
}
|
||||||
|
expect_stdout: "null 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_1b: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
return a && a;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(42));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(42));
|
||||||
|
}
|
||||||
|
expect_stdout: "null 42"
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_1c: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(delete (NaN && NaN));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(delete (0, NaN));
|
||||||
|
}
|
||||||
|
expect_stdout: "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_2a: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a || (a || b);
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a || b;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined {}",
|
||||||
|
"42 42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_2b: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a || (a && b);
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"null null",
|
||||||
|
"42 42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_2c: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a && (a || b);
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"null null",
|
||||||
|
"42 42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_2d: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a && (a && b);
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a && b;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"null null",
|
||||||
|
"undefined {}",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_3a: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a || ((a || b) || c);
|
||||||
|
}
|
||||||
|
console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));
|
||||||
|
console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a || b || c;
|
||||||
|
}
|
||||||
|
console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));
|
||||||
|
console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined {} true true",
|
||||||
|
"42 42 42 42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_3b: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a || ((a || b) && c);
|
||||||
|
}
|
||||||
|
console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));
|
||||||
|
console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a || b && c;
|
||||||
|
}
|
||||||
|
console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));
|
||||||
|
console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"false false undefined {}",
|
||||||
|
"42 42 42 42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_3c: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a || ((a && b) || c);
|
||||||
|
}
|
||||||
|
console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));
|
||||||
|
console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a || c;
|
||||||
|
}
|
||||||
|
console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));
|
||||||
|
console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined {} undefined {}",
|
||||||
|
"42 42 42 42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_3d: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a || ((a && b) && c);
|
||||||
|
}
|
||||||
|
console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));
|
||||||
|
console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));
|
||||||
|
console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"null null null null",
|
||||||
|
"42 42 42 42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_3e: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a && ((a || b) || c);
|
||||||
|
}
|
||||||
|
console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));
|
||||||
|
console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));
|
||||||
|
console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"null null null null",
|
||||||
|
"42 42 42 42",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_3f: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a && ((a || b) && c);
|
||||||
|
}
|
||||||
|
console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));
|
||||||
|
console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a && c;
|
||||||
|
}
|
||||||
|
console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));
|
||||||
|
console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"null null null null",
|
||||||
|
"undefined {} undefined {}",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_3g: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a && ((a && b) || c);
|
||||||
|
}
|
||||||
|
console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));
|
||||||
|
console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a && (b || c);
|
||||||
|
}
|
||||||
|
console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));
|
||||||
|
console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"null null null null",
|
||||||
|
"undefined {} true true",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_3h: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a && ((a && b) && c);
|
||||||
|
}
|
||||||
|
console.log(f(null, false), f(null, false, {}), f(null, true), f(null, true, {}));
|
||||||
|
console.log(f(42, false), f(42, false, {}), f(42, true), f(42, true, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b, c) {
|
||||||
|
return a && b && c;
|
||||||
|
}
|
||||||
|
console.log(f(null, !1), f(null, !1, {}), f(null, !0), f(null, !0, {}));
|
||||||
|
console.log(f(42, !1), f(42, !1, {}), f(42, !0), f(42, !0, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"null null null null",
|
||||||
|
"false false undefined {}",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
conditional_chain: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a ? a : b ? b : 42;
|
||||||
|
}
|
||||||
|
console.log(f("PASS", "FAIL"));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a || b || 42;
|
||||||
|
}
|
||||||
|
console.log(f("PASS", "FAIL"));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_3465_1: {
|
issue_3465_1: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
@@ -181,3 +558,79 @@ issue_4374: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "0"
|
expect_stdout: "0"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5028_1: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
console.log(function() {
|
||||||
|
return a-- ? a-- ? "FAIL 1" : "PASS" : "FAIL 2";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
console.log(function() {
|
||||||
|
return a-- ? a-- ? "FAIL 1" : "PASS" : "FAIL 2";
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5028_2: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
dead_code: true,
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
(function() {
|
||||||
|
if (a--)
|
||||||
|
if (a--)
|
||||||
|
a = "FAIL";
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
(function() {
|
||||||
|
a-- && a-- && (a = "FAIL");
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "-1"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5028_3: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
if_return: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
(function() {
|
||||||
|
if (a--)
|
||||||
|
if (a--)
|
||||||
|
a = "FAIL";
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
(function() {
|
||||||
|
a-- && a-- && (a = "FAIL");
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "-1"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1748,3 +1748,130 @@ issue_4992: {
|
|||||||
expect_stdout: "function"
|
expect_stdout: "function"
|
||||||
node_version: ">=12"
|
node_version: ">=12"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4996_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
console.log(new class A {
|
||||||
|
p = a-- && new A();
|
||||||
|
}().p.p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
console.log(new class A {
|
||||||
|
p = a-- && new A();
|
||||||
|
}().p.p);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
node_version: ">=12"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4996_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = 1;
|
||||||
|
console.log(new class A {
|
||||||
|
p = a-- && new A();
|
||||||
|
}().p.p);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = 1;
|
||||||
|
console.log(new class A {
|
||||||
|
p = a-- && new A();
|
||||||
|
}().p.p);
|
||||||
|
}
|
||||||
|
expect_stdout: "0"
|
||||||
|
node_version: ">=12"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5015_1: {
|
||||||
|
options = {
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
var a;
|
||||||
|
try {
|
||||||
|
(class a {
|
||||||
|
[a]() {}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
var a;
|
||||||
|
try {
|
||||||
|
(class a {
|
||||||
|
[a]() {}
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5015_2: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
try {
|
||||||
|
new class A {
|
||||||
|
[(A, 42)]() {}
|
||||||
|
}();
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
try {
|
||||||
|
new class A {
|
||||||
|
[(A, 42)]() {}
|
||||||
|
}();
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5015_3: {
|
||||||
|
options = {
|
||||||
|
reduce_vars: true,
|
||||||
|
side_effects: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
(class A {
|
||||||
|
static f() {
|
||||||
|
return A;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -4728,7 +4728,7 @@ cascade_statement: {
|
|||||||
}
|
}
|
||||||
function f3(a, b) {
|
function f3(a, b) {
|
||||||
for (; a < b; a++)
|
for (; a < b; a++)
|
||||||
if (c = a, a && b)
|
if ((c = a) && b)
|
||||||
var c = c = b(a);
|
var c = c = b(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8863,7 +8863,7 @@ issue_4732_1: {
|
|||||||
expect: {
|
expect: {
|
||||||
var a = 0;
|
var a = 0;
|
||||||
(function(b) {
|
(function(b) {
|
||||||
(b = a++) && (b && console.log("PASS"));
|
(b = a++) && console.log("PASS");
|
||||||
})(a++);
|
})(a++);
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
|
|||||||
@@ -822,6 +822,33 @@ cond_13: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cond_14: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
if (a)
|
||||||
|
if (a)
|
||||||
|
console.log("PASS");
|
||||||
|
else
|
||||||
|
console.log("FAIL");
|
||||||
|
}
|
||||||
|
f(null);
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
a && console.log("PASS");
|
||||||
|
}
|
||||||
|
f(null);
|
||||||
|
f(42);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
ternary_boolean_consequent: {
|
ternary_boolean_consequent: {
|
||||||
options = {
|
options = {
|
||||||
booleans: true,
|
booleans: true,
|
||||||
|
|||||||
@@ -939,6 +939,185 @@ catch_return_assign: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
catch_return_assign_may_throw: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
return e = console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
return console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
finally_return_assign: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} finally {
|
||||||
|
return a = "PASS";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} finally {
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
last_assign_statement: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
a = a("PASS");
|
||||||
|
}
|
||||||
|
f(console.log);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
a("PASS");
|
||||||
|
}
|
||||||
|
f(console.log);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
last_assign_if_else: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
if (a)
|
||||||
|
a = console.log("foo");
|
||||||
|
else {
|
||||||
|
console.log("bar");
|
||||||
|
a = console.log("baz");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f(42);
|
||||||
|
f(null);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
if (a)
|
||||||
|
console.log("foo");
|
||||||
|
else {
|
||||||
|
console.log("bar");
|
||||||
|
console.log("baz");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f(42);
|
||||||
|
f(null);
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"baz",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
last_assign_catch: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
e = console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
try {
|
||||||
|
throw "FAIL";
|
||||||
|
} catch (e) {
|
||||||
|
console.log("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
last_assign_finally: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
try {
|
||||||
|
throw a.log;
|
||||||
|
} catch (e) {
|
||||||
|
a = e;
|
||||||
|
} finally {
|
||||||
|
a = a("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f(console);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
try {
|
||||||
|
throw a.log;
|
||||||
|
} catch (e) {
|
||||||
|
a = e;
|
||||||
|
} finally {
|
||||||
|
a("PASS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f(console);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
consecutive_assignments: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
while (a = void 0, a = "PASS", console.log(a));
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
while (void 0, a = "PASS", console.log(a));
|
||||||
|
var a;
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_3578: {
|
issue_3578: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
@@ -1420,3 +1599,37 @@ issue_4570: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "NaN"
|
expect_stdout: "NaN"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5030: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a, b) {
|
||||||
|
a = function f() {
|
||||||
|
if (a)
|
||||||
|
if (b--)
|
||||||
|
setImmediate(f);
|
||||||
|
else
|
||||||
|
console.log("FAIL");
|
||||||
|
else
|
||||||
|
console.log("PASS");
|
||||||
|
}();
|
||||||
|
})(42, 1);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a, b) {
|
||||||
|
a = function f() {
|
||||||
|
if (a)
|
||||||
|
if (b--)
|
||||||
|
setImmediate(f);
|
||||||
|
else
|
||||||
|
console.log("FAIL");
|
||||||
|
else
|
||||||
|
console.log("PASS");
|
||||||
|
}();
|
||||||
|
})(42, 1);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=0.12"
|
||||||
|
}
|
||||||
|
|||||||
@@ -422,7 +422,9 @@ inline_loop_1: {
|
|||||||
inline_loop_2: {
|
inline_loop_2: {
|
||||||
options = {
|
options = {
|
||||||
inline: true,
|
inline: true,
|
||||||
|
sequences: true,
|
||||||
toplevel: true,
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
while (function(a = [ "PASS" ]) {
|
while (function(a = [ "PASS" ]) {
|
||||||
@@ -432,10 +434,11 @@ inline_loop_2: {
|
|||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
while (a = [ "PASS" ], a = function f(b) {
|
while (a = [ "PASS" ],
|
||||||
console.log(a[b]);
|
b = void 0,
|
||||||
}(0), void 0) ;
|
b = 0,
|
||||||
var a;
|
void (a = void console.log(a[b])));
|
||||||
|
var a, b;
|
||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
@@ -1726,3 +1729,28 @@ issue_4916: {
|
|||||||
expect_stdout: "undefined"
|
expect_stdout: "undefined"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4994: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function(b = function() {
|
||||||
|
for (a in { PASS: 42 });
|
||||||
|
}()) {
|
||||||
|
var a;
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function(b = function() {
|
||||||
|
for (a in { PASS: 42 });
|
||||||
|
}()) {})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
@@ -2592,3 +2592,58 @@ issue_4608_2: {
|
|||||||
expect_stdout: "f"
|
expect_stdout: "f"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4994: {
|
||||||
|
options = {
|
||||||
|
loops: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function([
|
||||||
|
{
|
||||||
|
[function() {
|
||||||
|
for (a in { PASS: null });
|
||||||
|
}()]: b,
|
||||||
|
},
|
||||||
|
]) {
|
||||||
|
var a;
|
||||||
|
})([ 42 ]);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "FAIL";
|
||||||
|
(function([
|
||||||
|
{
|
||||||
|
[function() {
|
||||||
|
for (a in { PASS: null });
|
||||||
|
}()]: b,
|
||||||
|
},
|
||||||
|
]) {})([ 42 ]);
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5017: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = function() {};
|
||||||
|
var b = c = a;
|
||||||
|
var c = [ c ] = [ c ];
|
||||||
|
console.log(c[0] === a ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = function() {};
|
||||||
|
var b = a;
|
||||||
|
var c = [ c ] = [ c = a ];
|
||||||
|
console.log(c[0] === a ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
@@ -6228,3 +6228,58 @@ recursive_collapse: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5025: {
|
||||||
|
options = {
|
||||||
|
collapse_vars: true,
|
||||||
|
inline: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
function g() {
|
||||||
|
b = 42;
|
||||||
|
}
|
||||||
|
g(b = a);
|
||||||
|
var b = this;
|
||||||
|
console.log(typeof b);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
b = a,
|
||||||
|
void (b = 42);
|
||||||
|
var b = this;
|
||||||
|
console.log(typeof b);
|
||||||
|
}
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
expect_stdout: "object"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5036: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
var await = function f() {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
return await() === await;
|
||||||
|
}() ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(typeof function() {
|
||||||
|
function await() {
|
||||||
|
return await;
|
||||||
|
}
|
||||||
|
return await() === await;
|
||||||
|
}() ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|||||||
@@ -94,13 +94,15 @@ drop_unused: {
|
|||||||
}
|
}
|
||||||
input: {
|
input: {
|
||||||
import a, * as b from "foo";
|
import a, * as b from "foo";
|
||||||
import { c, bar as d } from "baz";
|
import { c } from "bar";
|
||||||
console.log(c);
|
import { d, _ as e } from "baz";
|
||||||
|
console.log(d);
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
import "foo";
|
import "foo";
|
||||||
import { c as c } from "baz";
|
import "bar";
|
||||||
console.log(c);
|
import { d as d } from "baz";
|
||||||
|
console.log(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1015,7 +1015,7 @@ issue_3856: {
|
|||||||
console.log(function() {
|
console.log(function() {
|
||||||
(function() {
|
(function() {
|
||||||
var a, b;
|
var a, b;
|
||||||
if (a) return !!a;
|
if (a) return a, 1;
|
||||||
for (a = 0; !console;);
|
for (a = 0; !console;);
|
||||||
return 0;
|
return 0;
|
||||||
})();
|
})();
|
||||||
|
|||||||
@@ -1158,8 +1158,8 @@ replace_all_var_scope: {
|
|||||||
var a = 100, b = 10;
|
var a = 100, b = 10;
|
||||||
(function(r, a) {
|
(function(r, a) {
|
||||||
switch (~a) {
|
switch (~a) {
|
||||||
case (b += a):
|
case (b += a):
|
||||||
case a++:
|
case a++:
|
||||||
}
|
}
|
||||||
})(--b, a);
|
})(--b, a);
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
@@ -1168,8 +1168,8 @@ replace_all_var_scope: {
|
|||||||
var a = 100, b = 10;
|
var a = 100, b = 10;
|
||||||
(function(c) {
|
(function(c) {
|
||||||
switch (~a) {
|
switch (~a) {
|
||||||
case (b += a):
|
case (b += a):
|
||||||
case c++:
|
case c++:
|
||||||
}
|
}
|
||||||
})((--b, a));
|
})((--b, a));
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
|
|||||||
@@ -3075,7 +3075,7 @@ issue_4237_2: {
|
|||||||
console.log(function(a) {
|
console.log(function(a) {
|
||||||
do {
|
do {
|
||||||
switch (0) {
|
switch (0) {
|
||||||
case 0:
|
default:
|
||||||
var b = a++;
|
var b = a++;
|
||||||
if (b)
|
if (b)
|
||||||
return "FAIL";
|
return "FAIL";
|
||||||
|
|||||||
@@ -110,6 +110,158 @@ conditional_assignment_4: {
|
|||||||
node_version: ">=14"
|
node_version: ">=14"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
de_morgan_1: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a) {
|
||||||
|
return a ?? a;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(42));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(42));
|
||||||
|
}
|
||||||
|
expect_stdout: "null 42"
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_2a: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a || (a ?? b);
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a || (a ?? b);
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined {}",
|
||||||
|
"42 42",
|
||||||
|
]
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_2b: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a && (a ?? b);
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"null null",
|
||||||
|
"42 42",
|
||||||
|
]
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_2c: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
side_effects: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a ?? (a || b);
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a ?? b;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined {}",
|
||||||
|
"42 42",
|
||||||
|
]
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_2d: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
evaluate: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a ?? (a && b);
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"null null",
|
||||||
|
"42 42",
|
||||||
|
]
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
|
|
||||||
|
de_morgan_2e: {
|
||||||
|
options = {
|
||||||
|
booleans: true,
|
||||||
|
conditionals: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a ?? (a ?? b);
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f(a, b) {
|
||||||
|
return a ?? b;
|
||||||
|
}
|
||||||
|
console.log(f(null), f(null, {}));
|
||||||
|
console.log(f(42), f(42, {}));
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"undefined {}",
|
||||||
|
"42 42",
|
||||||
|
]
|
||||||
|
node_version: ">=14"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4679: {
|
issue_4679: {
|
||||||
options = {
|
options = {
|
||||||
comparisons: true,
|
comparisons: true,
|
||||||
|
|||||||
@@ -2071,72 +2071,6 @@ issue_1670_2: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
issue_1670_3: {
|
issue_1670_3: {
|
||||||
options = {
|
|
||||||
comparisons: true,
|
|
||||||
conditionals: true,
|
|
||||||
dead_code: true,
|
|
||||||
evaluate: true,
|
|
||||||
reduce_funcs: true,
|
|
||||||
reduce_vars: true,
|
|
||||||
side_effects: true,
|
|
||||||
switches: true,
|
|
||||||
typeofs: true,
|
|
||||||
unused: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
(function f() {
|
|
||||||
switch (1) {
|
|
||||||
case 0:
|
|
||||||
var a = true;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if (typeof a === "undefined") console.log("PASS");
|
|
||||||
else console.log("FAIL");
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
(function() {
|
|
||||||
var a;
|
|
||||||
void 0 === a ? console.log("PASS") : console.log("FAIL");
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
expect_stdout: "PASS"
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_1670_4: {
|
|
||||||
options = {
|
|
||||||
conditionals: true,
|
|
||||||
dead_code: true,
|
|
||||||
evaluate: true,
|
|
||||||
passes: 2,
|
|
||||||
reduce_funcs: true,
|
|
||||||
reduce_vars: true,
|
|
||||||
side_effects: true,
|
|
||||||
switches: true,
|
|
||||||
unused: true,
|
|
||||||
}
|
|
||||||
input: {
|
|
||||||
(function f() {
|
|
||||||
switch (1) {
|
|
||||||
case 0:
|
|
||||||
var a = true;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if (typeof a === "undefined") console.log("PASS");
|
|
||||||
else console.log("FAIL");
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
expect: {
|
|
||||||
(function() {
|
|
||||||
console.log("PASS");
|
|
||||||
})();
|
|
||||||
}
|
|
||||||
expect_stdout: "PASS"
|
|
||||||
}
|
|
||||||
|
|
||||||
issue_1670_5: {
|
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
@@ -2168,7 +2102,7 @@ issue_1670_5: {
|
|||||||
expect_stdout: "1"
|
expect_stdout: "1"
|
||||||
}
|
}
|
||||||
|
|
||||||
issue_1670_6: {
|
issue_1670_4: {
|
||||||
options = {
|
options = {
|
||||||
conditionals: true,
|
conditionals: true,
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
|
|||||||
@@ -1156,3 +1156,23 @@ issue_4882_3: {
|
|||||||
]
|
]
|
||||||
node_version: ">=8"
|
node_version: ">=8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5006: {
|
||||||
|
options = {
|
||||||
|
arguments: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(b, c) {
|
||||||
|
c = "FAIL 2";
|
||||||
|
return arguments[1];
|
||||||
|
}(...[], "FAIL 1") || "PASS");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(b, c) {
|
||||||
|
c = "FAIL 2";
|
||||||
|
return arguments[1];
|
||||||
|
}(...[], "FAIL 1") || "PASS");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=6"
|
||||||
|
}
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ constant_switch_5: {
|
|||||||
// the break inside the if ruins our job
|
// the break inside the if ruins our job
|
||||||
// we can still get rid of irrelevant cases.
|
// we can still get rid of irrelevant cases.
|
||||||
switch (1) {
|
switch (1) {
|
||||||
case 1:
|
default:
|
||||||
x();
|
x();
|
||||||
if (foo) break;
|
if (foo) break;
|
||||||
y();
|
y();
|
||||||
@@ -300,6 +300,37 @@ drop_default_2: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drop_default_3: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
console.log("PASS");
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
switch (42) {
|
||||||
|
case f():
|
||||||
|
break;
|
||||||
|
case void console.log("FAIL"):
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
console.log("PASS");
|
||||||
|
return 42;
|
||||||
|
}
|
||||||
|
switch (42) {
|
||||||
|
case f():
|
||||||
|
case void console.log("FAIL"):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
keep_default: {
|
keep_default: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
@@ -423,7 +454,6 @@ drop_case_3: {
|
|||||||
switch ({}.p) {
|
switch ({}.p) {
|
||||||
default:
|
default:
|
||||||
case void 0:
|
case void 0:
|
||||||
break;
|
|
||||||
case c = "FAIL":
|
case c = "FAIL":
|
||||||
}
|
}
|
||||||
console.log(c);
|
console.log(c);
|
||||||
@@ -454,7 +484,168 @@ drop_case_4: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
keep_case: {
|
drop_case_5: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (42) {
|
||||||
|
case void console.log("PASS 1"):
|
||||||
|
console.log("FAIL 1");
|
||||||
|
case 42:
|
||||||
|
case console.log("FAIL 2"):
|
||||||
|
console.log("PASS 2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (42) {
|
||||||
|
default:
|
||||||
|
void console.log("PASS 1");
|
||||||
|
console.log("PASS 2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS 1",
|
||||||
|
"PASS 2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_case_6: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (console.log("PASS 1"), 2) {
|
||||||
|
case 0:
|
||||||
|
console.log("FAIL 1");
|
||||||
|
case (console.log("PASS 2"), 1):
|
||||||
|
console.log("FAIL 2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (console.log("PASS 1"), 2) {
|
||||||
|
case (console.log("PASS 2"), 1):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS 1",
|
||||||
|
"PASS 2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_case_7: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (2) {
|
||||||
|
case 0:
|
||||||
|
console.log("FAIL 1");
|
||||||
|
case (console.log("PASS 1"), 1):
|
||||||
|
console.log("FAIL 2");
|
||||||
|
case 2:
|
||||||
|
console.log("PASS 2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (2) {
|
||||||
|
default:
|
||||||
|
console.log("PASS 1"), 1;
|
||||||
|
console.log("PASS 2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS 1",
|
||||||
|
"PASS 2",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_case_8: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(msg) {
|
||||||
|
console.log(msg);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
switch (log("foo")) {
|
||||||
|
case "bar":
|
||||||
|
log("moo");
|
||||||
|
break;
|
||||||
|
case log("baz"):
|
||||||
|
log("moo");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log("moo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(msg) {
|
||||||
|
console.log(msg);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
switch (log("foo")) {
|
||||||
|
case "bar":
|
||||||
|
case log("baz"):
|
||||||
|
default:
|
||||||
|
log("moo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"baz",
|
||||||
|
"moo",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_case_9: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(msg) {
|
||||||
|
console.log(msg);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
switch (log("foo")) {
|
||||||
|
case log("bar"):
|
||||||
|
log("moo");
|
||||||
|
break;
|
||||||
|
case "baz":
|
||||||
|
log("moo");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log("moo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(msg) {
|
||||||
|
console.log(msg);
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
switch (log("foo")) {
|
||||||
|
default:
|
||||||
|
log("bar");
|
||||||
|
log("moo");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
"moo",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_case_1: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
switches: true,
|
switches: true,
|
||||||
@@ -474,6 +665,76 @@ keep_case: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keep_case_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch ("foo") {
|
||||||
|
case console.log("bar"):
|
||||||
|
case console.log("baz"), "moo":
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch ("foo") {
|
||||||
|
case console.log("bar"):
|
||||||
|
case console.log("baz"), "moo":
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"bar",
|
||||||
|
"baz",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_case_3: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
switch (void console.log("PASS")) {
|
||||||
|
case a:
|
||||||
|
case console.log("FAIL"), 42:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
switch (void console.log("PASS")) {
|
||||||
|
case a:
|
||||||
|
case console.log("FAIL"), 42:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_case_4: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
switch (void console.log("PASS")) {
|
||||||
|
case a:
|
||||||
|
case void console.log("FAIL"):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
switch (void console.log("PASS")) {
|
||||||
|
case a:
|
||||||
|
case void console.log("FAIL"):
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
issue_376: {
|
issue_376: {
|
||||||
options = {
|
options = {
|
||||||
dead_code: true,
|
dead_code: true,
|
||||||
@@ -661,7 +922,7 @@ issue_1680_1: {
|
|||||||
case f(0):
|
case f(0):
|
||||||
case f(1):
|
case f(1):
|
||||||
f(2);
|
f(2);
|
||||||
case 2:
|
default:
|
||||||
f(5);
|
f(5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -924,7 +1185,6 @@ issue_2535: {
|
|||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
w(), 42;
|
w(), 42;
|
||||||
42;
|
|
||||||
y();
|
y();
|
||||||
z();
|
z();
|
||||||
}
|
}
|
||||||
@@ -950,7 +1210,6 @@ issue_1750: {
|
|||||||
expect: {
|
expect: {
|
||||||
var a = 0, b = 1;
|
var a = 0, b = 1;
|
||||||
true;
|
true;
|
||||||
a, true;
|
|
||||||
b = 2;
|
b = 2;
|
||||||
console.log(a, b);
|
console.log(a, b);
|
||||||
}
|
}
|
||||||
@@ -1088,7 +1347,8 @@ drop_switch_6: {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect: {
|
expect: {
|
||||||
A === B;
|
A;
|
||||||
|
B;
|
||||||
x();
|
x();
|
||||||
C !== D;
|
C !== D;
|
||||||
y();
|
y();
|
||||||
@@ -1181,3 +1441,170 @@ issue_4059: {
|
|||||||
}
|
}
|
||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5008_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
switches: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function f() {
|
||||||
|
switch (f) {
|
||||||
|
case f:
|
||||||
|
return "PASS";
|
||||||
|
default:
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function f() {
|
||||||
|
switch (f) {
|
||||||
|
default:
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5008_2: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
switches: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
switch (a) {
|
||||||
|
case a:
|
||||||
|
return "PASS";
|
||||||
|
default:
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
|
}([]));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
switch (a) {
|
||||||
|
default:
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}([]));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5008_3: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
switches: true,
|
||||||
|
unsafe: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
switch (a) {
|
||||||
|
case a:
|
||||||
|
return "PASS";
|
||||||
|
default:
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
|
}({}));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
switch (a) {
|
||||||
|
default:
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}({}));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5008_4: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function(a) {
|
||||||
|
switch (a) {
|
||||||
|
case a:
|
||||||
|
return "PASS";
|
||||||
|
default:
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
|
}(/foo/));
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function(a) {
|
||||||
|
switch (a) {
|
||||||
|
default:
|
||||||
|
return "PASS";
|
||||||
|
}
|
||||||
|
}(/foo/));
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5010: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a;
|
||||||
|
switch (42) {
|
||||||
|
case console.log("PASS"):
|
||||||
|
case a:
|
||||||
|
console.log("FAIL");
|
||||||
|
case 42:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a;
|
||||||
|
switch (42) {
|
||||||
|
case console.log("PASS"):
|
||||||
|
case a:
|
||||||
|
console.log("FAIL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5012: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
evaluate: true,
|
||||||
|
switches: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
switch (void 0) {
|
||||||
|
case console.log("PASS"):
|
||||||
|
break;
|
||||||
|
case void 0:
|
||||||
|
case 42:
|
||||||
|
console.log("FAIL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
switch (void 0) {
|
||||||
|
case console.log("PASS"):
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log("FAIL");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
}
|
||||||
@@ -1083,3 +1083,166 @@ issue_4769_2: {
|
|||||||
expect_stdout: "PASS"
|
expect_stdout: "PASS"
|
||||||
node_version: ">=6"
|
node_version: ">=6"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_5019_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
(function(a) {
|
||||||
|
return a = function*() {
|
||||||
|
console.log(typeof a);
|
||||||
|
}();
|
||||||
|
})().next();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
(function(a) {
|
||||||
|
return a = function*() {
|
||||||
|
console.log(typeof a);
|
||||||
|
}();
|
||||||
|
})().next();
|
||||||
|
}
|
||||||
|
expect_stdout: "object"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5019_2: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
toplevel: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = [];
|
||||||
|
for (var b in "foo")
|
||||||
|
a.push(function(c) {
|
||||||
|
return function*() {
|
||||||
|
console.log(c);
|
||||||
|
}();
|
||||||
|
}(b));
|
||||||
|
a.map(function(d) {
|
||||||
|
return d.next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = [];
|
||||||
|
for (var b in "foo")
|
||||||
|
a.push(function(c) {
|
||||||
|
return function*() {
|
||||||
|
console.log(c);
|
||||||
|
}();
|
||||||
|
}(b));
|
||||||
|
a.map(function(d) {
|
||||||
|
return d.next();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"0",
|
||||||
|
"1",
|
||||||
|
"2",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5032_normal: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
webkit: false,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(value) {
|
||||||
|
console.log(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
function *f(a) {
|
||||||
|
var b = log(a), c = b;
|
||||||
|
log(b);
|
||||||
|
log(c);
|
||||||
|
}
|
||||||
|
f("PASS").next();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(value) {
|
||||||
|
console.log(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
function *f(c) {
|
||||||
|
var b = log(c), c = b;
|
||||||
|
log(b);
|
||||||
|
log(c);
|
||||||
|
}
|
||||||
|
f("PASS").next();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5032_webkit: {
|
||||||
|
options = {
|
||||||
|
merge_vars: true,
|
||||||
|
webkit: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
function log(value) {
|
||||||
|
console.log(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
function *f(a) {
|
||||||
|
var b = log(a), c = b;
|
||||||
|
log(b);
|
||||||
|
log(c);
|
||||||
|
}
|
||||||
|
f("PASS").next();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function log(value) {
|
||||||
|
console.log(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
function *f(a) {
|
||||||
|
var b = log(a), c = b;
|
||||||
|
log(b);
|
||||||
|
log(c);
|
||||||
|
}
|
||||||
|
f("PASS").next();
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
"PASS",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_5034: {
|
||||||
|
options = {
|
||||||
|
functions: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
console.log(function() {
|
||||||
|
var yield = function f() {
|
||||||
|
return function*() {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
return yield()().next().value === yield;
|
||||||
|
}() ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
console.log(function() {
|
||||||
|
var yield = function f() {
|
||||||
|
return function*() {
|
||||||
|
return f;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
return yield()().next().value === yield;
|
||||||
|
}() ? "PASS" : "FAIL");
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|||||||
@@ -43,6 +43,9 @@ rm -rf tmp/rollup \
|
|||||||
- "postpublish": "pinst --enable",
|
- "postpublish": "pinst --enable",
|
||||||
- "prepare": "npm run build",
|
- "prepare": "npm run build",
|
||||||
- "prepublishOnly": "pinst --disable && npm ci && npm run lint:nofix && npm run security && npm run build:bootstrap && npm run test:all",
|
- "prepublishOnly": "pinst --disable && npm ci && npm run lint:nofix && npm run security && npm run build:bootstrap && npm run test:all",
|
||||||
|
@@ -93 +89 @@
|
||||||
|
- "is-reference": "lukastaegert/is-reference#update-class-features",
|
||||||
|
+ "is-reference": "3.0.0",
|
||||||
--- a/test/cli/index.js
|
--- a/test/cli/index.js
|
||||||
+++ b/test/cli/index.js
|
+++ b/test/cli/index.js
|
||||||
@@ -13,0 +14,3 @@ sander.rimrafSync(__dirname, 'node_modules');
|
@@ -13,0 +14,3 @@ sander.rimrafSync(__dirname, 'node_modules');
|
||||||
|
|||||||
Reference in New Issue
Block a user