drop unused "class" definition IIFEs (#2923)

fixes #805
This commit is contained in:
Alex Lam S.L
2018-02-17 05:11:31 +08:00
committed by GitHub
parent e529f54e90
commit 7fdd2082a6
4 changed files with 124 additions and 15 deletions

View File

@@ -2004,7 +2004,7 @@ merge(Compressor.prototype, {
if (this.properties[i].value instanceof AST_Accessor) return true; if (this.properties[i].value instanceof AST_Accessor) return true;
return false; return false;
}); });
def(AST_Function, return_false); def(AST_Lambda, return_false);
def(AST_UnaryPostfix, return_false); def(AST_UnaryPostfix, return_false);
def(AST_UnaryPrefix, function() { def(AST_UnaryPrefix, function() {
return this.operator == "void"; return this.operator == "void";
@@ -2023,8 +2023,9 @@ merge(Compressor.prototype, {
}) })
def(AST_Dot, function(compressor) { def(AST_Dot, function(compressor) {
if (!is_strict(compressor)) return false; if (!is_strict(compressor)) return false;
if (this.expression instanceof AST_Function && this.property == "prototype") return false; var exp = this.expression;
return true; if (exp instanceof AST_SymbolRef) exp = exp.fixed_value();
return !(exp instanceof AST_Lambda && this.property == "prototype");
}); });
def(AST_Sequence, function(compressor) { def(AST_Sequence, function(compressor) {
return this.tail_node()._dot_throw(compressor); return this.tail_node()._dot_throw(compressor);
@@ -3009,11 +3010,18 @@ merge(Compressor.prototype, {
if (self.uses_eval || self.uses_with) return; if (self.uses_eval || self.uses_with) return;
var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs; var drop_funcs = !(self instanceof AST_Toplevel) || compressor.toplevel.funcs;
var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars; var drop_vars = !(self instanceof AST_Toplevel) || compressor.toplevel.vars;
var assign_as_unused = /keep_assign/.test(compressor.option("unused")) ? return_false : function(node) { var assign_as_unused = /keep_assign/.test(compressor.option("unused")) ? return_false : function(node, props) {
var sym;
if (node instanceof AST_Assign && (node.write_only || node.operator == "=")) { if (node instanceof AST_Assign && (node.write_only || node.operator == "=")) {
return node.left; sym = node.left;
} else if (node instanceof AST_Unary && node.write_only) {
sym = node.expression;
} }
if (node instanceof AST_Unary && node.write_only) return node.expression; while (sym instanceof AST_PropAccess && !sym.expression.may_throw_on_access(compressor)) {
if (sym instanceof AST_Sub) props.unshift(sym.property);
sym = sym.expression;
}
return sym;
}; };
var in_use = []; var in_use = [];
var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use var in_use_ids = Object.create(null); // avoid expensive linear scans of in_use
@@ -3089,18 +3097,27 @@ merge(Compressor.prototype, {
function before(node, descend, in_list) { function before(node, descend, in_list) {
var parent = tt.parent(); var parent = tt.parent();
if (drop_vars) { if (drop_vars) {
var sym = assign_as_unused(node); var props = [], sym = assign_as_unused(node, props);
if (sym instanceof AST_SymbolRef) { if (sym instanceof AST_SymbolRef) {
var def = sym.definition(); var def = sym.definition();
var in_use = def.id in in_use_ids; var in_use = def.id in in_use_ids;
var value = null;
if (node instanceof AST_Assign) { if (node instanceof AST_Assign) {
if (!in_use || def.id in fixed_ids && fixed_ids[def.id] !== node) { if (!in_use || node.left === sym && def.id in fixed_ids && fixed_ids[def.id] !== node) {
return maintain_this_binding(parent, node, node.right.transform(tt)); value = node.right;
} }
} else if (!in_use) return make_node(AST_Number, node, { } else if (!in_use) {
value = make_node(AST_Number, node, {
value: 0 value: 0
}); });
} }
if (value) {
props.push(value);
return maintain_this_binding(parent, node, make_sequence(node, props.map(function(prop) {
return prop.transform(tt);
})));
}
}
} }
if (scope !== self) return; if (scope !== self) return;
if (node instanceof AST_Function if (node instanceof AST_Function
@@ -3277,12 +3294,15 @@ merge(Compressor.prototype, {
self.transform(tt); self.transform(tt);
function scan_ref_scoped(node, descend) { function scan_ref_scoped(node, descend) {
var node_def, sym = assign_as_unused(node); var node_def, props = [], sym = assign_as_unused(node, props);
if (sym instanceof AST_SymbolRef if (sym instanceof AST_SymbolRef
&& self.variables.get(sym.name) === (node_def = sym.definition())) { && self.variables.get(sym.name) === (node_def = sym.definition())) {
props.forEach(function(prop) {
prop.walk(tw);
});
if (node instanceof AST_Assign) { if (node instanceof AST_Assign) {
node.right.walk(tw); node.right.walk(tw);
if (!node_def.chained && node.left.fixed_value() === node.right) { if (node.left === sym && !node_def.chained && sym.fixed_value() === node.right) {
fixed_ids[node_def.id] = node; fixed_ids[node_def.id] = node;
} }
} }

View File

@@ -4619,3 +4619,26 @@ issue_2914_2: {
} }
expect_stdout: "0" expect_stdout: "0"
} }
issue_805: {
options = {
collapse_vars: true,
pure_getters: "strict",
reduce_vars: true,
}
input: {
function f() {
function Foo(){}
Foo.prototype = {};
Foo.prototype.bar = 42;
return Foo;
}
}
expect: {
function f() {
function Foo(){}
(Foo.prototype = {}).bar = 42;
return Foo;
}
}
}

View File

@@ -1719,3 +1719,69 @@ issue_2846: {
} }
expect_stdout: "0" expect_stdout: "0"
} }
issue_805_1: {
options = {
inline: true,
passes: 2,
pure_getters: "strict",
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
(function(a) {
var unused = function() {};
unused.prototype[a()] = 42;
(unused.prototype.bar = function() {
console.log("bar");
})();
return unused;
})(function() {
console.log("foo");
return "foo";
});
}
expect: {
console.log("foo"),
console.log("bar");
}
expect_stdout: [
"foo",
"bar",
]
}
issue_805_2: {
options = {
inline: true,
passes: 2,
pure_getters: "strict",
reduce_vars: true,
sequences: true,
side_effects: true,
unused: true,
}
input: {
(function(a) {
function unused() {}
unused.prototype[a()] = 42;
(unused.prototype.bar = function() {
console.log("bar");
})();
return unused;
})(function() {
console.log("foo");
return "foo";
});
}
expect: {
console.log("foo"),
console.log("bar");
}
expect_stdout: [
"foo",
"bar",
]
}

View File

@@ -38,7 +38,7 @@ describe("test/jetstream.js", function() {
this.timeout(20 * 60 * 1000); this.timeout(20 * 60 * 1000);
[ [
"-mc", "-mc",
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto", "-mc keep_fargs=false,passes=3,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
].forEach(function(options) { ].forEach(function(options) {
it("Should pass with options " + options, function(done) { it("Should pass with options " + options, function(done) {
var args = options.split(/ /); var args = options.split(/ /);