From 21aff996a5d54730a1b67a51f3e79a89a7abd53f Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Mon, 21 Nov 2022 03:30:02 +0000 Subject: [PATCH] enhance `varify` (#5737) --- lib/compress.js | 46 ++++++++++++++++++++++++++++++++++++----- lib/minify.js | 2 +- test/compress/varify.js | 36 ++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 6 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index a9a8ca93..5305f7a6 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -98,7 +98,7 @@ function Compressor(options, false_by_default) { switches : !false_by_default, templates : !false_by_default, top_retain : null, - toplevel : !!(options && (options["module"] || options["top_retain"])), + toplevel : !!(options && !options["expression"] && (options["module"] || options["top_retain"])), typeofs : !false_by_default, unsafe : false, unsafe_comps : false, @@ -9357,7 +9357,7 @@ Compressor.prototype.compress = function(node) { OPT(AST_ForEnumeration, function(self, compressor) { if (compressor.option("varify") && is_lexical_definition(self.init)) { var name = self.init.definitions[0].name; - if ((name instanceof AST_Destructured || name instanceof AST_SymbolLet) + if ((compressor.option("module") || name instanceof AST_Destructured || name instanceof AST_SymbolLet) && !name.match_symbol(function(node) { if (node instanceof AST_SymbolDeclaration) { var def = node.definition(); @@ -9365,6 +9365,8 @@ Compressor.prototype.compress = function(node) { } }, true)) { self.init = to_var(self.init, self.resolve()); + } else if (can_letify(self.init, compressor, 1)) { + self.init = to_let(self.init); } } return self; @@ -10178,6 +10180,20 @@ Compressor.prototype.compress = function(node) { } } + function to_let(stat) { + return make_node(AST_Let, stat, { + definitions: stat.definitions.map(function(defn) { + return make_node(AST_VarDef, defn, { + name: defn.name.convert_symbol(AST_SymbolLet, function(name, node) { + var def = name.definition(); + def.orig[def.orig.indexOf(node)] = name; + }), + value: defn.value, + }); + }), + }); + } + function to_var(stat, scope) { return make_node(AST_Var, stat, { definitions: stat.definitions.map(function(defn) { @@ -10197,6 +10213,18 @@ Compressor.prototype.compress = function(node) { }); } + function can_letify(stat, compressor, assigned) { + if (!(stat instanceof AST_Const)) return false; + if (!compressor.option("module") && all(stat.definitions, function(defn) { + return defn.name instanceof AST_SymbolConst; + })) return false; + return all(stat.definitions, function(defn) { + return !defn.name.match_symbol(function(node) { + if (node instanceof AST_SymbolDeclaration) return node.definition().assignments != assigned; + }, true); + }); + } + function can_varify(compressor, sym) { var def = sym.definition(); return (def.fixed || def.fixed === 0) @@ -10206,15 +10234,23 @@ Compressor.prototype.compress = function(node) { } function varify(self, compressor) { - return compressor.option("varify") && all(self.definitions, function(defn) { + return all(self.definitions, function(defn) { return !defn.name.match_symbol(function(node) { if (node instanceof AST_SymbolDeclaration) return !can_varify(compressor, node); }, true); }) ? to_var(self, compressor.find_parent(AST_Scope)) : self; } - OPT(AST_Const, varify); - OPT(AST_Let, varify); + OPT(AST_Const, function(self, compressor) { + if (!compressor.option("varify")) return self; + if (can_letify(self, compressor, 0)) return to_let(self); + return varify(self, compressor); + }); + + OPT(AST_Let, function(self, compressor) { + if (!compressor.option("varify")) return self; + return varify(self, compressor); + }); function trim_optional_chain(node, compressor) { if (!compressor.option("optional_chains")) return; diff --git a/lib/minify.js b/lib/minify.js index c7a1341c..ff4bb65c 100644 --- a/lib/minify.js +++ b/lib/minify.js @@ -89,7 +89,7 @@ function minify(files, options) { rename: undefined, sourceMap: false, timings: false, - toplevel: !!(options && options["module"]), + toplevel: !!(options && !options["expression"] && options["module"]), v8: false, validate: false, warnings: false, diff --git a/test/compress/varify.js b/test/compress/varify.js index a7d983a6..c9f67f42 100644 --- a/test/compress/varify.js +++ b/test/compress/varify.js @@ -329,6 +329,42 @@ forin_const_2: { node_version: ">=6" } +forin_const_3: { + options = { + module: true, + reduce_vars: true, + toplevel: true, + varify: true, + } + input: { + "use strict"; + const o = { + p: 42, + q: "PASS", + }; + for (const k in o) + (function f() { + console.log(k, o[k]); + })(); + } + expect: { + "use strict"; + let o = { + p: 42, + q: "PASS", + }; + for (let k in o) + (function f() { + console.log(k, o[k]); + })(); + } + expect_stdout: [ + "p 42", + "q PASS", + ] + node_version: ">=4" +} + forin_let_1: { options = { join_vars: true,