diff options
-rw-r--r-- | lib/compress.js | 100 | ||||
-rw-r--r-- | test/compress/async.js | 48 | ||||
-rw-r--r-- | test/compress/const.js | 24 | ||||
-rw-r--r-- | test/compress/default-values.js | 18 | ||||
-rw-r--r-- | test/compress/destructured.js | 18 | ||||
-rw-r--r-- | test/compress/hoist_vars.js | 25 | ||||
-rw-r--r-- | test/ufuzz/options.json | 3 |
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 }, { |