aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2021-06-20 08:30:04 +0100
committerGitHub <noreply@github.com>2021-06-20 15:30:04 +0800
commitfd8dec61ad0e83caa72691b56e1d36b6f29203a8 (patch)
tree6cd5e0ba7d136c4c0365983d8ea4c18dea98cc6d
parent7880568d157fcd1c15c0f392e4646e01de363afd (diff)
downloadtracifyjs-fd8dec61ad0e83caa72691b56e1d36b6f29203a8.tar.gz
tracifyjs-fd8dec61ad0e83caa72691b56e1d36b6f29203a8.zip
enhance `dead_code` (#5014)
-rw-r--r--lib/compress.js91
-rw-r--r--test/compress/dead-code.js164
-rwxr-xr-xtest/release/rollup-ts.sh3
3 files changed, 231 insertions, 27 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 22434f62..5a7461a8 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -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();
@@ -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 {
@@ -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")) {
@@ -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);
}
});
diff --git a/test/compress/dead-code.js b/test/compress/dead-code.js
index 9101869d..4493deb0 100644
--- a/test/compress/dead-code.js
+++ b/test/compress/dead-code.js
@@ -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,
diff --git a/test/release/rollup-ts.sh b/test/release/rollup-ts.sh
index 503aeadf..4763911d 100755
--- a/test/release/rollup-ts.sh
+++ b/test/release/rollup-ts.sh
@@ -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');