Skip to content

Commit

Permalink
enhance dead_code (#5014)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexlamsl committed Jun 20, 2021
1 parent 7880568 commit fd8dec6
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 27 deletions.
91 changes: 64 additions & 27 deletions lib/compress.js
Original file line number Diff line number Diff line change
Expand Up @@ -1714,6 +1714,15 @@ merge(Compressor.prototype, {
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) {
var in_loop, in_try, scope;
find_loop_scope_try();
Expand Down Expand Up @@ -3168,15 +3177,6 @@ merge(Compressor.prototype, {
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) {
var block = self, stat, level = 0;
do {
Expand Down Expand Up @@ -11140,28 +11140,36 @@ merge(Compressor.prototype, {
if (node instanceof AST_PropAccess) return true;
if (!found && node instanceof AST_SymbolRef && node.definition() === def) {
if (in_try(level, parent)) return true;
def.fixed = false;
found = true;
}
})) break;
if (found) return strip_assignment();
} else if (parent instanceof AST_Exit) {
if (!found) continue;
return strip_assignment(def);
}
if (parent instanceof AST_Exit) {
if (!local) break;
if (in_try(level, parent)) break;
if (is_reachable(scope, [ def ])) break;
def.fixed = false;
return strip_assignment();
} else if (parent instanceof AST_VarDef) {
return strip_assignment(def);
}
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.definition() !== def) continue;
if (in_try(level, parent)) break;
def.fixed = false;
return strip_assignment();
return strip_assignment(def);
}
} while (parent instanceof AST_Binary && parent.right === node
|| parent instanceof AST_Conditional && parent.condition !== node
|| parent instanceof AST_Sequence && parent.tail_node() === node
|| parent instanceof AST_UnaryPrefix);
} while (is_tail(node, parent));
}
}
if (compressor.option("sequences")) {
Expand Down Expand Up @@ -11206,26 +11214,55 @@ merge(Compressor.prototype, {
}
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) {
var right = self.right;
self.right = make_node(AST_Null, right);
var may_throw = node.may_throw(compressor);
self.right = right;
var parent;
while (parent = compressor.parent(level++)) {
for (var parent; parent = compressor.parent(level++); node = parent) {
if (parent === scope) return false;
if (parent instanceof AST_Try) {
if (parent.bfinally) return true;
if (may_throw && parent.bcatch) return true;
if (parent.bfinally && parent.bfinally !== node) 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, {
operator: self.operator.slice(0, -1),
left: self.left,
right: self.right
right: self.right,
}) : maintain_this_binding(compressor, compressor.parent(), self, self.right)).optimize(compressor);
}
});
Expand Down
164 changes: 164 additions & 0 deletions test/compress/dead-code.js
Original file line number Diff line number Diff line change
Expand Up @@ -939,6 +939,170 @@ catch_return_assign: {
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"
}

issue_3578: {
options = {
dead_code: true,
Expand Down
3 changes: 3 additions & 0 deletions test/release/rollup-ts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ rm -rf tmp/rollup \
- "postpublish": "pinst --enable",
- "prepare": "npm run build",
- "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
+++ b/test/cli/index.js
@@ -13,0 +14,3 @@ sander.rimrafSync(__dirname, 'node_modules');
Expand Down

0 comments on commit fd8dec6

Please sign in to comment.