aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2021-05-30 09:32:48 +0100
committerGitHub <noreply@github.com>2021-05-30 16:32:48 +0800
commit06e3dbc08916d70f3ca26cd89f8b442b23593332 (patch)
treebca869edc0e61b0aa7961b77c01aa65cc9b6f037
parent55a230daa84a004058d8cde0e15543bb2647dc3c (diff)
downloadtracifyjs-06e3dbc08916d70f3ca26cd89f8b442b23593332.tar.gz
tracifyjs-06e3dbc08916d70f3ca26cd89f8b442b23593332.zip
improve handling of declaration statements (#4980)
-rw-r--r--lib/compress.js25
-rw-r--r--test/compress/functions.js2
-rw-r--r--test/compress/let.js108
3 files changed, 127 insertions, 8 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 34d36a0c..b20a41e5 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -325,9 +325,12 @@ merge(Compressor.prototype, {
} else if (insert === "awaits" && node instanceof AST_Try) {
if (node.bfinally) return node;
}
- var index = node.body.length - 1;
- if (index >= 0) {
- node.body[index] = node.body[index].transform(tt);
+ for (var index = node.body.length; --index >= 0;) {
+ var stat = node.body[index];
+ if (!is_declaration(stat, true)) {
+ node.body[index] = stat.transform(tt);
+ break;
+ }
}
} else if (node instanceof AST_If) {
node.body = node.body.transform(tt);
@@ -1695,8 +1698,16 @@ merge(Compressor.prototype, {
});
}
- function is_declaration(stat) {
- return stat instanceof AST_Defun || stat instanceof AST_Var && declarations_only(stat);
+ function is_declaration(stat, lexical) {
+ if (stat instanceof AST_DefClass) return lexical && !stat.extends && all(stat.properties, function(prop) {
+ if (prop.key instanceof AST_Node) return false;
+ if (prop instanceof AST_ClassField && prop.static && prop.value) return false;
+ return true;
+ });
+ if (stat instanceof AST_Definitions) return (lexical || stat instanceof AST_Var) && declarations_only(stat);
+ if (stat instanceof AST_ExportDeclaration) return is_declaration(stat.body, lexical);
+ if (stat instanceof AST_ExportDefault) return is_declaration(stat.body, lexical);
+ return stat instanceof AST_LambdaDefinition;
}
function tighten_body(statements, compressor) {
@@ -3157,7 +3168,7 @@ merge(Compressor.prototype, {
var index = body.lastIndexOf(stat);
if (index < 0) return false;
while (++index < body.length) {
- if (!is_declaration(body[index])) return false;
+ if (!is_declaration(body[index], true)) return false;
}
return true;
}
@@ -7970,7 +7981,7 @@ merge(Compressor.prototype, {
self.condition,
]);
body.splice(i, 1);
- } else if (!is_declaration(stat)) {
+ } else if (!is_declaration(stat, true)) {
break;
}
}
diff --git a/test/compress/functions.js b/test/compress/functions.js
index 8ab7c1fc..988f589e 100644
--- a/test/compress/functions.js
+++ b/test/compress/functions.js
@@ -5236,7 +5236,7 @@ issue_4265: {
expect: {
function f() {
return console, function() {
- return console.log(a);
+ console.log(a);
var a;
}(), 0;
}
diff --git a/test/compress/let.js b/test/compress/let.js
index 64526aa7..0a23f65b 100644
--- a/test/compress/let.js
+++ b/test/compress/let.js
@@ -569,6 +569,38 @@ loop_block_2: {
node_version: ">=4"
}
+do_break: {
+ options = {
+ loops: true,
+ }
+ input: {
+ "use strict";
+ try {
+ do {
+ if (a)
+ break;
+ let a;
+ } while (!console);
+ } catch (e) {
+ console.log("PASS");
+ }
+ }
+ expect: {
+ "use strict";
+ try {
+ do {
+ if (a)
+ break;
+ let a;
+ } while (!console);
+ } catch (e) {
+ console.log("PASS");
+ }
+ }
+ expect_stdout: "PASS"
+ node_version: ">=4"
+}
+
do_continue: {
options = {
loops: true,
@@ -629,6 +661,82 @@ dead_block_after_return: {
node_version: ">=4"
}
+if_return_1: {
+ options = {
+ if_return: true,
+ }
+ input: {
+ "use strict";
+ function f(a) {
+ function g() {
+ return b = "PASS";
+ }
+ if (a)
+ return g();
+ let b;
+ return g();
+ };
+ console.log(f());
+ }
+ expect: {
+ "use strict";
+ function f(a) {
+ function g() {
+ return b = "PASS";
+ }
+ if (a)
+ return g();
+ let b;
+ return g();
+ };
+ console.log(f());
+ }
+ expect_stdout: "PASS"
+ node_version: ">=4"
+}
+
+if_return_2: {
+ options = {
+ if_return: true,
+ }
+ input: {
+ "use strict";
+ function f(a) {
+ function g() {
+ return b = "FAIL";
+ }
+ if (a)
+ return g();
+ let b;
+ return g();
+ };
+ try {
+ console.log(f(42));
+ } catch (e) {
+ console.log("PASS");
+ }
+ }
+ expect: {
+ "use strict";
+ function f(a) {
+ function g() {
+ return b = "FAIL";
+ }
+ if (a)
+ return g();
+ let b;
+ return g();
+ };
+ try {
+ console.log(f(42));
+ } catch (e) {
+ console.log("PASS");
+ }
+ }
+ expect_stdout: "PASS"
+ node_version: ">=4"
+}
+
do_if_continue_1: {
options = {
if_return: true,