@@ -340,8 +340,7 @@ merge(Compressor.prototype, {
|
|||||||
return !immutable
|
return !immutable
|
||||||
&& parent.expression === node
|
&& parent.expression === node
|
||||||
&& !parent.is_expr_pure(compressor)
|
&& !parent.is_expr_pure(compressor)
|
||||||
&& (!(value instanceof AST_Function)
|
&& (!is_function(value) || !(parent instanceof AST_New) && value.contains_this());
|
||||||
|| !(parent instanceof AST_New) && value.contains_this());
|
|
||||||
}
|
}
|
||||||
if (parent instanceof AST_ForIn) return parent.init === node;
|
if (parent instanceof AST_ForIn) return parent.init === node;
|
||||||
if (parent instanceof AST_ObjectKeyVal) {
|
if (parent instanceof AST_ObjectKeyVal) {
|
||||||
@@ -390,13 +389,13 @@ merge(Compressor.prototype, {
|
|||||||
def.fixed = !def.const_redefs
|
def.fixed = !def.const_redefs
|
||||||
&& !def.scope.pinned()
|
&& !def.scope.pinned()
|
||||||
&& !compressor.exposed(def)
|
&& !compressor.exposed(def)
|
||||||
&& !(def.init instanceof AST_Function && def.init !== def.scope)
|
&& !(is_function(def.init) && def.init !== def.scope)
|
||||||
&& def.init;
|
&& def.init;
|
||||||
if (def.fixed instanceof AST_Defun && !all(def.references, function(ref) {
|
if (is_defun(def.fixed) && !all(def.references, function(ref) {
|
||||||
var scope = ref.scope.resolve();
|
var scope = ref.scope.resolve();
|
||||||
do {
|
do {
|
||||||
if (def.scope === scope) return true;
|
if (def.scope === scope) return true;
|
||||||
} while (scope instanceof AST_Function && (scope = scope.parent_scope.resolve()));
|
} while (is_function(scope) && (scope = scope.parent_scope.resolve()));
|
||||||
})) {
|
})) {
|
||||||
tw.defun_ids[def.id] = false;
|
tw.defun_ids[def.id] = false;
|
||||||
}
|
}
|
||||||
@@ -421,7 +420,7 @@ merge(Compressor.prototype, {
|
|||||||
scope.may_call_this = noop;
|
scope.may_call_this = noop;
|
||||||
if (!scope.contains_this()) return;
|
if (!scope.contains_this()) return;
|
||||||
scope.functions.each(function(def) {
|
scope.functions.each(function(def) {
|
||||||
if (def.init instanceof AST_Defun && !(def.id in tw.defun_ids)) {
|
if (is_defun(def.init) && !(def.id in tw.defun_ids)) {
|
||||||
tw.defun_ids[def.id] = false;
|
tw.defun_ids[def.id] = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -458,7 +457,7 @@ merge(Compressor.prototype, {
|
|||||||
|
|
||||||
function walk_defuns(tw, scope) {
|
function walk_defuns(tw, scope) {
|
||||||
scope.functions.each(function(def) {
|
scope.functions.each(function(def) {
|
||||||
if (def.init instanceof AST_Defun && !tw.defun_visited[def.id]) {
|
if (is_defun(def.init) && !tw.defun_visited[def.id]) {
|
||||||
tw.defun_ids[def.id] = tw.safe_ids;
|
tw.defun_ids[def.id] = tw.safe_ids;
|
||||||
def.init.walk(tw);
|
def.init.walk(tw);
|
||||||
}
|
}
|
||||||
@@ -496,7 +495,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
return !safe.assign || safe.assign === tw.safe_ids;
|
return !safe.assign || safe.assign === tw.safe_ids;
|
||||||
}
|
}
|
||||||
return def.fixed instanceof AST_Defun;
|
return is_defun(def.fixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
function safe_to_assign(tw, def, declare) {
|
function safe_to_assign(tw, def, declare) {
|
||||||
@@ -651,6 +650,20 @@ merge(Compressor.prototype, {
|
|||||||
lhs.walk(scanner);
|
lhs.walk(scanner);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function reduce_defun(tw, descend, compressor) {
|
||||||
|
var id = this.name.definition().id;
|
||||||
|
if (tw.defun_visited[id]) return true;
|
||||||
|
if (tw.defun_ids[id] !== tw.safe_ids) return true;
|
||||||
|
tw.defun_visited[id] = true;
|
||||||
|
this.inlined = false;
|
||||||
|
push(tw);
|
||||||
|
reset_variables(tw, compressor, this);
|
||||||
|
descend();
|
||||||
|
pop(tw);
|
||||||
|
walk_defuns(tw, this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
def(AST_Assign, function(tw, descend, compressor) {
|
def(AST_Assign, function(tw, descend, compressor) {
|
||||||
var node = this;
|
var node = this;
|
||||||
var left = node.left;
|
var left = node.left;
|
||||||
@@ -732,6 +745,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
def(AST_AsyncDefun, reduce_defun);
|
||||||
def(AST_Binary, function(tw) {
|
def(AST_Binary, function(tw) {
|
||||||
if (!lazy_op[this.operator]) return;
|
if (!lazy_op[this.operator]) return;
|
||||||
this.left.walk(tw);
|
this.left.walk(tw);
|
||||||
@@ -748,31 +762,27 @@ merge(Compressor.prototype, {
|
|||||||
def(AST_Call, function(tw, descend) {
|
def(AST_Call, function(tw, descend) {
|
||||||
tw.find_parent(AST_Scope).may_call_this();
|
tw.find_parent(AST_Scope).may_call_this();
|
||||||
var exp = this.expression;
|
var exp = this.expression;
|
||||||
var tail = exp.tail_node();
|
if (is_function(exp)) {
|
||||||
if (tail instanceof AST_Function) {
|
|
||||||
if (exp !== tail) exp.expressions.slice(0, -1).forEach(function(node) {
|
|
||||||
node.walk(tw);
|
|
||||||
});
|
|
||||||
this.args.forEach(function(arg) {
|
this.args.forEach(function(arg) {
|
||||||
arg.walk(tw);
|
arg.walk(tw);
|
||||||
});
|
});
|
||||||
tail.walk(tw);
|
exp.walk(tw);
|
||||||
return true;
|
return true;
|
||||||
} else if (tail instanceof AST_SymbolRef) {
|
} else if (exp instanceof AST_SymbolRef) {
|
||||||
var def = tail.definition();
|
var def = exp.definition();
|
||||||
if (this.TYPE == "Call" && tw.in_boolean_context()) def.bool_fn++;
|
if (this.TYPE == "Call" && tw.in_boolean_context()) def.bool_fn++;
|
||||||
if (!(def.fixed instanceof AST_Defun)) return;
|
if (!is_defun(def.fixed)) return;
|
||||||
var defun = mark_defun(tw, def);
|
var defun = mark_defun(tw, def);
|
||||||
if (!defun) return;
|
if (!defun) return;
|
||||||
descend();
|
descend();
|
||||||
defun.walk(tw);
|
defun.walk(tw);
|
||||||
return true;
|
return true;
|
||||||
} else if (this.TYPE == "Call"
|
} else if (this.TYPE == "Call"
|
||||||
&& tail instanceof AST_Assign
|
&& exp instanceof AST_Assign
|
||||||
&& tail.operator == "="
|
&& exp.operator == "="
|
||||||
&& tail.left instanceof AST_SymbolRef
|
&& exp.left instanceof AST_SymbolRef
|
||||||
&& tw.in_boolean_context()) {
|
&& tw.in_boolean_context()) {
|
||||||
tail.left.definition().bool_fn++;
|
exp.left.definition().bool_fn++;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
def(AST_Conditional, function(tw) {
|
def(AST_Conditional, function(tw) {
|
||||||
@@ -785,19 +795,7 @@ merge(Compressor.prototype, {
|
|||||||
pop(tw);
|
pop(tw);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
def(AST_Defun, function(tw, descend, compressor) {
|
def(AST_Defun, reduce_defun);
|
||||||
var id = this.name.definition().id;
|
|
||||||
if (tw.defun_visited[id]) return true;
|
|
||||||
if (tw.defun_ids[id] !== tw.safe_ids) return true;
|
|
||||||
tw.defun_visited[id] = true;
|
|
||||||
this.inlined = false;
|
|
||||||
push(tw);
|
|
||||||
reset_variables(tw, compressor, this);
|
|
||||||
descend();
|
|
||||||
pop(tw);
|
|
||||||
walk_defuns(tw, this);
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
def(AST_Do, function(tw) {
|
def(AST_Do, function(tw) {
|
||||||
var saved_loop = tw.in_loop;
|
var saved_loop = tw.in_loop;
|
||||||
tw.in_loop = this;
|
tw.in_loop = this;
|
||||||
@@ -1007,8 +1005,7 @@ merge(Compressor.prototype, {
|
|||||||
}
|
}
|
||||||
if (!this.fixed) this.fixed = d.fixed;
|
if (!this.fixed) this.fixed = d.fixed;
|
||||||
var parent;
|
var parent;
|
||||||
if (d.fixed instanceof AST_Defun
|
if (is_defun(d.fixed) && !((parent = tw.parent()) instanceof AST_Call && parent.expression === this)) {
|
||||||
&& !((parent = tw.parent()) instanceof AST_Call && parent.expression === this)) {
|
|
||||||
var defun = mark_defun(tw, d);
|
var defun = mark_defun(tw, d);
|
||||||
if (defun) defun.walk(tw);
|
if (defun) defun.walk(tw);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -328,3 +328,62 @@ property_access_expression: {
|
|||||||
expect_stdout: "function"
|
expect_stdout: "function"
|
||||||
node_version: ">=8"
|
node_version: ">=8"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_4347_1: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "foo";
|
||||||
|
f();
|
||||||
|
a = "bar";
|
||||||
|
f();
|
||||||
|
async function f() {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "foo";
|
||||||
|
f();
|
||||||
|
a = "bar";
|
||||||
|
f();
|
||||||
|
async function f() {
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_4347_2: {
|
||||||
|
options = {
|
||||||
|
evaluate: true,
|
||||||
|
reduce_vars: true,
|
||||||
|
toplevel: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
var a = "PASS";
|
||||||
|
(async function() {
|
||||||
|
throw 42;
|
||||||
|
a = "FAIL";
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
var a = "PASS";
|
||||||
|
(async function() {
|
||||||
|
throw 42;
|
||||||
|
a = "FAIL";
|
||||||
|
})();
|
||||||
|
console.log(a);
|
||||||
|
}
|
||||||
|
expect_stdout: "PASS"
|
||||||
|
node_version: ">=8"
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user