aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Lam S.L <alexlamsl@gmail.com>2019-11-17 02:36:42 +0800
committerGitHub <noreply@github.com>2019-11-17 02:36:42 +0800
commita6a0319f1c758013e8f1be9632fa30b031144835 (patch)
treeb5f4463a45cc39063215ae181b5c8ebc50df3096
parentd1b2ecec27ea17e42d504503c6d760ff3c67b9ad (diff)
downloadtracifyjs-a6a0319f1c758013e8f1be9632fa30b031144835.tar.gz
tracifyjs-a6a0319f1c758013e8f1be9632fa30b031144835.zip
compress empty for-in loops (#3590)
-rw-r--r--lib/compress.js41
-rw-r--r--test/compress/loops.js64
2 files changed, 92 insertions, 13 deletions
diff --git a/lib/compress.js b/lib/compress.js
index 9366091c..e85cf5d3 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -3912,19 +3912,6 @@ merge(Compressor.prototype, {
scope = save_scope;
return node;
}
-
- function log(sym, text, props) {
- AST_Node[sym.unreferenced() ? "warn" : "info"](text, props);
- }
-
- function template(sym) {
- return {
- name : sym.name,
- file : sym.start.file,
- line : sym.start.line,
- col : sym.start.col
- };
- }
}, function(node, in_list) {
if (node instanceof AST_For) {
// Certain combination of unused name + side effect leads to invalid AST:
@@ -3952,6 +3939,21 @@ merge(Compressor.prototype, {
node.init = null;
}
return !block ? node : in_list ? MAP.splice(block.body) : block;
+ } else if (node instanceof AST_ForIn) {
+ if (!drop_vars || !compressor.option("loops")) return;
+ if (!(node.init instanceof AST_Definitions)) return;
+ var sym = node.init.definitions[0].name;
+ if (sym.definition().id in in_use_ids) return;
+ if (!is_empty(node.body)) return;
+ log(sym, "Dropping unused loop variable {name} [{file}:{line},{col}]", template(sym));
+ var value = node.object.drop_side_effect_free(compressor);
+ if (value) {
+ AST_Node.warn("Side effects in object of for-in loop [{file}:{line},{col}]", template(sym));
+ return make_node(AST_SimpleStatement, node, {
+ body: value
+ });
+ }
+ return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
} else if (node instanceof AST_Sequence) {
if (node.expressions.length == 1) return node.expressions[0];
}
@@ -3962,6 +3964,19 @@ merge(Compressor.prototype, {
fn.name = null;
});
+ function log(sym, text, props) {
+ AST_Node[sym.unreferenced() ? "warn" : "info"](text, props);
+ }
+
+ function template(sym) {
+ return {
+ name: sym.name,
+ file: sym.start.file,
+ line: sym.start.line,
+ col : sym.start.col
+ };
+ }
+
function verify_safe_usage(def, read, modified) {
if (def.id in in_use_ids) return;
if (read && modified) {
diff --git a/test/compress/loops.js b/test/compress/loops.js
index d835080d..7b6002a2 100644
--- a/test/compress/loops.js
+++ b/test/compress/loops.js
@@ -689,3 +689,67 @@ step: {
}
expect_stdout: "42"
}
+
+empty_for_in: {
+ options = {
+ loops: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ for (var a in [ 1, 2, 3 ]) {
+ var b = a + 1;
+ }
+ }
+ expect: {}
+ expect_warnings: [
+ "WARN: Dropping unused variable b [test/compress/loops.js:2,16]",
+ "INFO: Dropping unused loop variable a [test/compress/loops.js:1,17]",
+ ]
+}
+
+empty_for_in_used: {
+ options = {
+ loops: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ for (var a in [ 1, 2, 3 ]) {
+ var b = a + 1;
+ }
+ console.log(a);
+ }
+ expect: {
+ for (var a in [ 1, 2, 3 ]);
+ console.log(a);
+ }
+ expect_stdout: "2"
+ expect_warnings: [
+ "WARN: Dropping unused variable b [test/compress/loops.js:2,16]",
+ ]
+}
+
+empty_for_in_side_effects: {
+ options = {
+ loops: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ for (var a in {
+ foo: console.log("PASS")
+ }) {
+ var b = a + "bar";
+ }
+ }
+ expect: {
+ console.log("PASS");
+ }
+ expect_stdout: "PASS"
+ expect_warnings: [
+ "WARN: Dropping unused variable b [test/compress/loops.js:4,16]",
+ "INFO: Dropping unused loop variable a [test/compress/loops.js:1,17]",
+ "WARN: Side effects in object of for-in loop [test/compress/loops.js:1,17]",
+ ]
+}