enhance side_effects & unused (#4711)
This commit is contained in:
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@@ -7,7 +7,7 @@ jobs:
|
|||||||
test:
|
test:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node: [ '0.8', '0.10', '0.12', '4', '6', '8', '10', '12', latest ]
|
node: [ '0.8', '0.10', '0.12', '4', '6', '8', '10', '12', '14', latest ]
|
||||||
os: [ ubuntu-latest, windows-latest ]
|
os: [ ubuntu-latest, windows-latest ]
|
||||||
script: [ compress, mocha, release/benchmark, release/jetstream ]
|
script: [ compress, mocha, release/benchmark, release/jetstream ]
|
||||||
exclude:
|
exclude:
|
||||||
|
|||||||
@@ -420,12 +420,14 @@ merge(Compressor.prototype, {
|
|||||||
} while (sym = sym.parent_scope);
|
} while (sym = sym.parent_scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
function can_drop_symbol(ref, keep_lambda) {
|
function can_drop_symbol(ref, compressor, keep_lambda) {
|
||||||
var def = ref.definition();
|
var def = ref.definition();
|
||||||
if (ref.in_arg && is_funarg(def)) return false;
|
if (ref.in_arg && is_funarg(def)) return false;
|
||||||
return all(def.orig, function(sym) {
|
return all(def.orig, function(sym) {
|
||||||
return !(sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet
|
if (sym instanceof AST_SymbolConst || sym instanceof AST_SymbolLet) {
|
||||||
|| keep_lambda && sym instanceof AST_SymbolLambda);
|
return compressor && can_varify(compressor, sym);
|
||||||
|
}
|
||||||
|
return !(keep_lambda && sym instanceof AST_SymbolLambda);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,6 +601,7 @@ merge(Compressor.prototype, {
|
|||||||
function is_immutable(value) {
|
function is_immutable(value) {
|
||||||
if (!value) return false;
|
if (!value) return false;
|
||||||
return value.is_constant()
|
return value.is_constant()
|
||||||
|
|| value instanceof AST_Class
|
||||||
|| value instanceof AST_Lambda
|
|| value instanceof AST_Lambda
|
||||||
|| value instanceof AST_ObjectIdentity;
|
|| value instanceof AST_ObjectIdentity;
|
||||||
}
|
}
|
||||||
@@ -3585,6 +3588,7 @@ merge(Compressor.prototype, {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
def(AST_Class, return_false);
|
||||||
def(AST_Conditional, function(compressor) {
|
def(AST_Conditional, function(compressor) {
|
||||||
return this.consequent._dot_throw(compressor) || this.alternative._dot_throw(compressor);
|
return this.consequent._dot_throw(compressor) || this.alternative._dot_throw(compressor);
|
||||||
});
|
});
|
||||||
@@ -3593,7 +3597,7 @@ merge(Compressor.prototype, {
|
|||||||
if (!is_strict(compressor)) return false;
|
if (!is_strict(compressor)) return false;
|
||||||
var exp = this.expression;
|
var exp = this.expression;
|
||||||
if (exp instanceof AST_SymbolRef) exp = exp.fixed_value();
|
if (exp instanceof AST_SymbolRef) exp = exp.fixed_value();
|
||||||
return !(exp instanceof AST_Lambda && this.property == "prototype");
|
return !(this.property == "prototype" && (exp instanceof AST_Class || exp instanceof AST_Lambda));
|
||||||
});
|
});
|
||||||
def(AST_Lambda, return_false);
|
def(AST_Lambda, return_false);
|
||||||
def(AST_Null, return_true);
|
def(AST_Null, return_true);
|
||||||
@@ -4869,7 +4873,7 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
def(AST_SymbolDeclaration, return_false);
|
def(AST_SymbolDeclaration, return_false);
|
||||||
def(AST_SymbolRef, function(compressor) {
|
def(AST_SymbolRef, function(compressor) {
|
||||||
return !this.is_declared(compressor) || !can_drop_symbol(this);
|
return !this.is_declared(compressor) || !can_drop_symbol(this, compressor);
|
||||||
});
|
});
|
||||||
def(AST_Template, function(compressor) {
|
def(AST_Template, function(compressor) {
|
||||||
return this.tag && !is_raw_tag(compressor, this.tag) || any(this.expressions, compressor);
|
return this.tag && !is_raw_tag(compressor, this.tag) || any(this.expressions, compressor);
|
||||||
@@ -5698,7 +5702,7 @@ merge(Compressor.prototype, {
|
|||||||
var def = sym.definition();
|
var def = sym.definition();
|
||||||
if (export_defaults[def.id]) return;
|
if (export_defaults[def.id]) return;
|
||||||
if (compressor.exposed(def)) return;
|
if (compressor.exposed(def)) return;
|
||||||
if (!can_drop_symbol(sym, nested)) return;
|
if (!can_drop_symbol(sym, compressor, nested)) return;
|
||||||
return sym;
|
return sym;
|
||||||
};
|
};
|
||||||
var assign_in_use = Object.create(null);
|
var assign_in_use = Object.create(null);
|
||||||
@@ -7418,7 +7422,7 @@ merge(Compressor.prototype, {
|
|||||||
return make_sequence(this, [ expression, property ]);
|
return make_sequence(this, [ expression, property ]);
|
||||||
});
|
});
|
||||||
def(AST_SymbolRef, function(compressor) {
|
def(AST_SymbolRef, function(compressor) {
|
||||||
return this.is_declared(compressor) && can_drop_symbol(this) ? null : this;
|
return this.is_declared(compressor) && can_drop_symbol(this, compressor) ? null : this;
|
||||||
});
|
});
|
||||||
def(AST_Template, function(compressor, first_in_statement) {
|
def(AST_Template, function(compressor, first_in_statement) {
|
||||||
if (this.tag && !is_raw_tag(compressor, this.tag)) return this;
|
if (this.tag && !is_raw_tag(compressor, this.tag)) return this;
|
||||||
@@ -7432,7 +7436,9 @@ merge(Compressor.prototype, {
|
|||||||
this.write_only = !exp.has_side_effects(compressor);
|
this.write_only = !exp.has_side_effects(compressor);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
if (this.operator == "typeof" && exp instanceof AST_SymbolRef && can_drop_symbol(exp)) return null;
|
if (this.operator == "typeof" && exp instanceof AST_SymbolRef && can_drop_symbol(exp, compressor)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
var node = exp.drop_side_effect_free(compressor, first_in_statement);
|
var node = exp.drop_side_effect_free(compressor, first_in_statement);
|
||||||
if (first_in_statement && node && is_iife_call(node)) {
|
if (first_in_statement && node && is_iife_call(node)) {
|
||||||
if (node === exp && this.operator == "!") return this;
|
if (node === exp && this.operator == "!") return this;
|
||||||
@@ -8237,13 +8243,16 @@ merge(Compressor.prototype, {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function can_varify(compressor, sym) {
|
||||||
|
if (!sym.fixed_value()) return false;
|
||||||
|
var def = sym.definition();
|
||||||
|
return is_safe_lexical(def) && !may_overlap(compressor, def);
|
||||||
|
}
|
||||||
|
|
||||||
function varify(self, compressor) {
|
function varify(self, compressor) {
|
||||||
return compressor.option("varify") && all(self.definitions, function(defn) {
|
return compressor.option("varify") && all(self.definitions, function(defn) {
|
||||||
return !defn.name.match_symbol(function(node) {
|
return !defn.name.match_symbol(function(node) {
|
||||||
if (node instanceof AST_SymbolDeclaration) {
|
if (node instanceof AST_SymbolDeclaration) return !can_varify(compressor, node);
|
||||||
var def = node.definition();
|
|
||||||
return !node.fixed_value() || !is_safe_lexical(def) || may_overlap(compressor, def);
|
|
||||||
}
|
|
||||||
}, true);
|
}, true);
|
||||||
}) ? to_var(self) : self;
|
}) ? to_var(self) : self;
|
||||||
}
|
}
|
||||||
@@ -9370,7 +9379,7 @@ merge(Compressor.prototype, {
|
|||||||
// always true in booleans
|
// always true in booleans
|
||||||
AST_Node.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
|
AST_Node.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
|
||||||
var exprs = [ make_node(AST_True, self) ];
|
var exprs = [ make_node(AST_True, self) ];
|
||||||
if (!(exp instanceof AST_SymbolRef && can_drop_symbol(exp))) exprs.unshift(exp);
|
if (!(exp instanceof AST_SymbolRef && can_drop_symbol(exp, compressor))) exprs.unshift(exp);
|
||||||
return make_sequence(self, exprs).optimize(compressor);
|
return make_sequence(self, exprs).optimize(compressor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ private_methods: {
|
|||||||
}
|
}
|
||||||
expect_exact: "(new class A{static*#f(){yield 3*A.#p}async #g(){for(var a of A.#f())return a*await 2}static get #p(){return 7}get q(){return this.#g()}}).q.then(console.log);"
|
expect_exact: "(new class A{static*#f(){yield 3*A.#p}async #g(){for(var a of A.#f())return a*await 2}static get #p(){return 7}get q(){return this.#g()}}).q.then(console.log);"
|
||||||
expect_stdout: "42"
|
expect_stdout: "42"
|
||||||
node_version: ">=14"
|
node_version: ">=14.6"
|
||||||
}
|
}
|
||||||
|
|
||||||
await: {
|
await: {
|
||||||
@@ -573,6 +573,78 @@ computed_key_generator: {
|
|||||||
node_version: ">=4"
|
node_version: ">=4"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
issue_805_1: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
(function(a) {
|
||||||
|
var unused = class {};
|
||||||
|
unused.prototype[a()] = 42;
|
||||||
|
(unused.prototype.bar = function() {
|
||||||
|
console.log("bar");
|
||||||
|
})();
|
||||||
|
return unused;
|
||||||
|
})(function() {
|
||||||
|
console.log("foo");
|
||||||
|
return "foo";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log("foo"),
|
||||||
|
console.log("bar");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
|
issue_805_2: {
|
||||||
|
options = {
|
||||||
|
inline: true,
|
||||||
|
passes: 2,
|
||||||
|
pure_getters: "strict",
|
||||||
|
reduce_vars: true,
|
||||||
|
sequences: true,
|
||||||
|
side_effects: true,
|
||||||
|
unused: true,
|
||||||
|
}
|
||||||
|
input: {
|
||||||
|
"use strict";
|
||||||
|
(function(a) {
|
||||||
|
class unused {}
|
||||||
|
unused.prototype[a()] = 42;
|
||||||
|
(unused.prototype.bar = function() {
|
||||||
|
console.log("bar");
|
||||||
|
})();
|
||||||
|
return unused;
|
||||||
|
})(function() {
|
||||||
|
console.log("foo");
|
||||||
|
return "foo";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
"use strict";
|
||||||
|
console.log("foo"),
|
||||||
|
console.log("bar");
|
||||||
|
}
|
||||||
|
expect_stdout: [
|
||||||
|
"foo",
|
||||||
|
"bar",
|
||||||
|
]
|
||||||
|
node_version: ">=4"
|
||||||
|
}
|
||||||
|
|
||||||
issue_4681: {
|
issue_4681: {
|
||||||
options = {
|
options = {
|
||||||
unused: true,
|
unused: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user