aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/compress.js100
-rw-r--r--test/compress/async.js48
-rw-r--r--test/compress/const.js24
-rw-r--r--test/compress/default-values.js18
-rw-r--r--test/compress/destructured.js18
-rw-r--r--test/compress/hoist_vars.js25
-rw-r--r--test/ufuzz/options.json3
7 files changed, 194 insertions, 42 deletions
diff --git a/lib/compress.js b/lib/compress.js
index c556c492..103f47f1 100644
--- a/lib/compress.js
+++ b/lib/compress.js
@@ -6171,6 +6171,7 @@ merge(Compressor.prototype, {
if (var_decl <= 1) hoist_vars = false;
}
if (!hoist_funs && !hoist_vars) return;
+ var consts = Object.create(null);
var dirs = [];
var hoisted = [];
var vars = new Dictionary(), vars_found = 0;
@@ -6186,6 +6187,12 @@ merge(Compressor.prototype, {
return make_node(AST_EmptyStatement, node);
}
if (hoist_vars && node instanceof AST_Var) {
+ if (!all(node.definitions, function(defn) {
+ var sym = defn.name;
+ return sym instanceof AST_SymbolVar
+ && !consts[sym.name]
+ && self.find_variable(sym.name) === sym.definition();
+ })) return node;
node.definitions.forEach(function(def) {
vars.set(def.name.name, def);
++vars_found;
@@ -6204,6 +6211,10 @@ merge(Compressor.prototype, {
});
}
if (node instanceof AST_Scope) return node;
+ if (node instanceof AST_SymbolConst) {
+ consts[node.name] = true;
+ return node;
+ }
});
self.transform(tt);
if (vars_found > 0) {
@@ -6224,48 +6235,7 @@ merge(Compressor.prototype, {
});
if (defs.length > 0) {
// try to merge in assignments
- for (var i = 0; i < self.body.length;) {
- if (self.body[i] instanceof AST_SimpleStatement) {
- var expr = self.body[i].body, sym, assign;
- if (expr instanceof AST_Assign
- && expr.operator == "="
- && (sym = expr.left) instanceof AST_Symbol
- && vars.has(sym.name))
- {
- var def = vars.get(sym.name);
- if (def.value) break;
- def.value = expr.right;
- remove(defs, def);
- defs.push(def);
- self.body.splice(i, 1);
- continue;
- }
- if (expr instanceof AST_Sequence
- && (assign = expr.expressions[0]) instanceof AST_Assign
- && assign.operator == "="
- && (sym = assign.left) instanceof AST_Symbol
- && vars.has(sym.name))
- {
- var def = vars.get(sym.name);
- if (def.value) break;
- def.value = assign.right;
- remove(defs, def);
- defs.push(def);
- self.body[i].body = make_sequence(expr, expr.expressions.slice(1));
- continue;
- }
- }
- if (self.body[i] instanceof AST_EmptyStatement) {
- self.body.splice(i, 1);
- continue;
- }
- if (self.body[i] instanceof AST_BlockStatement) {
- var tmp = [ i, 1 ].concat(self.body[i].body);
- self.body.splice.apply(self.body, tmp);
- continue;
- }
- break;
- }
+ insert_vars(self.body);
defs = make_node(AST_Var, self, {
definitions: defs
});
@@ -6273,6 +6243,50 @@ merge(Compressor.prototype, {
}
}
self.body = dirs.concat(hoisted, self.body);
+
+ function insert_vars(body) {
+ while (body.length) {
+ var stat = body[0];
+ if (stat instanceof AST_SimpleStatement) {
+ var expr = stat.body, sym, assign;
+ if (expr instanceof AST_Assign
+ && expr.operator == "="
+ && (sym = expr.left) instanceof AST_Symbol
+ && vars.has(sym.name)) {
+ var def = vars.get(sym.name);
+ if (def.value) break;
+ def.value = expr.right;
+ remove(defs, def);
+ defs.push(def);
+ body.shift();
+ continue;
+ }
+ if (expr instanceof AST_Sequence
+ && (assign = expr.expressions[0]) instanceof AST_Assign
+ && assign.operator == "="
+ && (sym = assign.left) instanceof AST_Symbol
+ && vars.has(sym.name)) {
+ var def = vars.get(sym.name);
+ if (def.value) break;
+ def.value = assign.right;
+ remove(defs, def);
+ defs.push(def);
+ stat.body = make_sequence(expr, expr.expressions.slice(1));
+ continue;
+ }
+ }
+ if (stat instanceof AST_EmptyStatement) {
+ body.shift();
+ continue;
+ }
+ if (stat instanceof AST_BlockStatement && !insert_vars(stat.body)) {
+ body.shift();
+ continue;
+ }
+ break;
+ }
+ return body.length;
+ }
});
function scan_local_returns(fn, transform) {
@@ -9352,6 +9366,8 @@ merge(Compressor.prototype, {
scope.inlined = true;
} while (scope = scope.parent_scope);
}
+ } else if (fixed.name && fixed.name.name == "await" && is_async(fixed)) {
+ single_use = false;
}
if (single_use) fixed.parent_scope = self.scope;
} else if (!fixed || !fixed.is_constant_expression()) {
diff --git a/test/compress/async.js b/test/compress/async.js
index 19b90f51..5d623bbe 100644
--- a/test/compress/async.js
+++ b/test/compress/async.js
@@ -32,6 +32,54 @@ defun_name: {
node_version: ">=8"
}
+drop_fname: {
+ rename = true
+ options = {
+ reduce_vars: true,
+ toplevel: true,
+ unused: true,
+ }
+ mangle = {
+ toplevel: true,
+ }
+ input: {
+ async function await() {
+ console.log("PASS");
+ }
+ await();
+ }
+ expect: {
+ (async function() {
+ console.log("PASS");
+ })();
+ }
+ expect_stdout: "PASS"
+ node_version: ">=8"
+}
+
+keep_fname: {
+ options = {
+ keep_fnames: true,
+ reduce_vars: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ async function await() {
+ console.log("PASS");
+ }
+ await();
+ }
+ expect: {
+ async function await() {
+ console.log("PASS");
+ }
+ await();
+ }
+ expect_stdout: "PASS"
+ node_version: ">=8"
+}
+
nested_await: {
input: {
(async function() {
diff --git a/test/compress/const.js b/test/compress/const.js
index 4eea1977..0281fd87 100644
--- a/test/compress/const.js
+++ b/test/compress/const.js
@@ -658,6 +658,30 @@ legacy_scope: {
expect_stdout: true
}
+hoist_vars: {
+ options = {
+ hoist_vars: true,
+ }
+ input: {
+ {
+ const a = "FAIL";
+ var b = 42;
+ }
+ var a = "PASS";
+ console.log(a, b);
+ }
+ expect: {
+ var b;
+ {
+ const a = "FAIL";
+ b = 42;
+ }
+ var a = "PASS";
+ console.log(a, b);
+ }
+ expect_stdout: true
+}
+
issue_4191: {
options = {
functions: true,
diff --git a/test/compress/default-values.js b/test/compress/default-values.js
index acd285f4..39fcddbd 100644
--- a/test/compress/default-values.js
+++ b/test/compress/default-values.js
@@ -505,6 +505,24 @@ drop_fargs: {
node_version: ">=6"
}
+hoist_vars: {
+ options = {
+ hoist_vars: true,
+ }
+ input: {
+ var a = "PASS";
+ var [ b = 42 ] = [];
+ console.log(a, b);
+ }
+ expect: {
+ var a = "PASS";
+ var [ b = 42 ] = [];
+ console.log(a, b);
+ }
+ expect_stdout: "PASS 42"
+ node_version: ">=6"
+}
+
unused_var_1: {
options = {
toplevel: true,
diff --git a/test/compress/destructured.js b/test/compress/destructured.js
index 98e84f48..ba7dbf3c 100644
--- a/test/compress/destructured.js
+++ b/test/compress/destructured.js
@@ -1358,6 +1358,24 @@ fn_name_unused: {
node_version: ">=6"
}
+hoist_vars: {
+ options = {
+ hoist_vars: true,
+ }
+ input: {
+ var a = "PASS";
+ var [ b ] = [ 42 ];
+ console.log(a, b);
+ }
+ expect: {
+ var a = "PASS";
+ var [ b ] = [ 42 ];
+ console.log(a, b);
+ }
+ expect_stdout: "PASS 42"
+ node_version: ">=6"
+}
+
issue_4280: {
options = {
evaluate: true,
diff --git a/test/compress/hoist_vars.js b/test/compress/hoist_vars.js
index 6aa1f7b4..6cd99b06 100644
--- a/test/compress/hoist_vars.js
+++ b/test/compress/hoist_vars.js
@@ -89,6 +89,31 @@ sequences_funs: {
}
}
+catch_var: {
+ options = {
+ dead_code: true,
+ hoist_vars: true,
+ side_effects: true,
+ toplevel: true,
+ unused: true,
+ }
+ input: {
+ var a = "PASS";
+ try {
+ a;
+ } catch (a) {
+ var a = 0;
+ a;
+ }
+ console.log(a);
+ }
+ expect: {
+ var a = "PASS";
+ console.log(a);
+ }
+ expect_stdout: "PASS"
+}
+
issue_2295: {
options = {
collapse_vars: true,
diff --git a/test/ufuzz/options.json b/test/ufuzz/options.json
index 1bdfd5b6..8f6dbe4e 100644
--- a/test/ufuzz/options.json
+++ b/test/ufuzz/options.json
@@ -21,9 +21,12 @@
},
{
"compress": {
+ "hoist_vars": true,
+ "keep_infinity": true,
"passes": 1e6,
"unsafe": true
},
+ "keep_fnames": true,
"toplevel": true
},
{