diff options
author | Alex Lam S.L <alexlamsl@gmail.com> | 2020-04-23 23:50:53 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-24 06:50:53 +0800 |
commit | 3ee13cae02174e565ca40462d7b15c4974265871 (patch) | |
tree | 1a7a9b09da324ff3cb238ac101637696e02cb781 | |
parent | 99cf3a38c53d4a8e4ac937962df4a0fdc600c070 (diff) | |
download | tracifyjs-3ee13cae02174e565ca40462d7b15c4974265871.tar.gz tracifyjs-3ee13cae02174e565ca40462d7b15c4974265871.zip |
improve `compress` (#3814)
- avoid identifier overflow through consecutive API calls
- simplify `reduce_vars`
- enhance `unsafe` `evaluate`
-rw-r--r-- | lib/compress.js | 17 | ||||
-rw-r--r-- | lib/scope.js | 29 | ||||
-rw-r--r-- | test/compress/reduce_vars.js | 19 |
3 files changed, 43 insertions, 22 deletions
diff --git a/lib/compress.js b/lib/compress.js index 7c2077b7..9420d8d2 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -460,7 +460,7 @@ merge(Compressor.prototype, { return def.fixed instanceof AST_Defun; } - function safe_to_assign(tw, def, scope, value) { + function safe_to_assign(tw, def, value) { if (def.fixed === undefined) return true; if (def.fixed === null && def.safe_ids) { def.safe_ids[def.id] = false; @@ -471,11 +471,8 @@ merge(Compressor.prototype, { if (!safe_to_read(tw, def)) return false; if (def.fixed === false) return false; if (def.fixed != null && (!value || def.references.length > def.assignments)) return false; - if (def.fixed instanceof AST_Defun) { - return value instanceof AST_Node && def.fixed.parent_scope === scope; - } return all(def.orig, function(sym) { - return !(sym instanceof AST_SymbolDefun || sym instanceof AST_SymbolLambda); + return !(sym instanceof AST_SymbolLambda); }); } @@ -557,7 +554,7 @@ merge(Compressor.prototype, { } if (sym.fixed) delete sym.fixed; var d = sym.definition(); - var safe = safe_to_assign(tw, d, sym.scope, node.right); + var safe = safe_to_assign(tw, d, node.right); d.assignments++; var fixed = d.fixed; if (!fixed && node.operator != "=") return; @@ -820,7 +817,7 @@ merge(Compressor.prototype, { } if (exp.fixed) delete exp.fixed; var d = exp.definition(); - var safe = safe_to_assign(tw, d, exp.scope, true); + var safe = safe_to_assign(tw, d, true); d.assignments++; var fixed = d.fixed; if (!fixed) return; @@ -846,7 +843,7 @@ merge(Compressor.prototype, { var node = this; var d = node.name.definition(); if (node.value) { - if (safe_to_assign(tw, d, node.name.scope, node.value)) { + if (safe_to_assign(tw, d, node.value)) { d.fixed = function() { return node.value; }; @@ -3195,7 +3192,7 @@ merge(Compressor.prototype, { def(AST_Statement, function() { throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start)); }); - def(AST_Lambda, return_this); + def(AST_Accessor, return_this); def(AST_Node, return_this); def(AST_Constant, function() { return this.value; @@ -3213,7 +3210,7 @@ merge(Compressor.prototype, { var value = node._eval(compressor, ignore_side_effects, cached, depth); return value === node ? this : value; }); - def(AST_Function, function(compressor) { + def(AST_Lambda, function(compressor) { if (compressor.option("unsafe")) { var fn = function() {}; fn.node = this; diff --git a/lib/scope.js b/lib/scope.js index ad33c5e0..adbfe4ac 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -43,23 +43,21 @@ "use strict"; -function SymbolDef(scope, orig, init) { +function SymbolDef(id, scope, orig, init) { + this.eliminated = 0; + this.global = false; + this.id = id; + this.init = init; + this.lambda = orig instanceof AST_SymbolLambda; + this.mangled_name = null; this.name = orig.name; this.orig = [ orig ]; - this.init = init; - this.eliminated = 0; - this.scope = scope; this.references = []; this.replaced = 0; - this.global = false; - this.mangled_name = null; + this.scope = scope; this.undeclared = false; - this.id = SymbolDef.next_id++; - this.lambda = orig instanceof AST_SymbolLambda; } -SymbolDef.next_id = 1; - SymbolDef.prototype = { unmangleable: function(options) { return this.global && !options.toplevel @@ -151,6 +149,7 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { scope.def_variable(node).defun = defun; } }); + self.next_def_id = 0; self.walk(tw); // pass 2: find back references and eval @@ -240,12 +239,18 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) { } }); +AST_Scope.DEFMETHOD("make_def", function(orig, init) { + var top = this; + while (top.parent_scope) top = top.parent_scope; + return new SymbolDef(++top.next_def_id, this, orig, init); +}); + AST_Toplevel.DEFMETHOD("def_global", function(node) { var globals = this.globals, name = node.name; if (globals.has(name)) { return globals.get(name); } else { - var g = new SymbolDef(this, node); + var g = this.make_def(node); g.undeclared = true; g.global = true; globals.set(name, g); @@ -310,7 +315,7 @@ AST_Scope.DEFMETHOD("def_variable", function(symbol, init) { def.orig.push(symbol); if (def.init instanceof AST_Function) def.init = init; } else { - def = new SymbolDef(this, symbol, init); + def = this.make_def(symbol, init); this.variables.set(symbol.name, def); def.global = !this.parent_scope; } diff --git a/test/compress/reduce_vars.js b/test/compress/reduce_vars.js index 6be1171f..25108cae 100644 --- a/test/compress/reduce_vars.js +++ b/test/compress/reduce_vars.js @@ -223,6 +223,25 @@ unsafe_evaluate: { expect_stdout: true } +unsafe_evaluate_defun: { + options = { + evaluate: true, + reduce_vars: true, + unsafe: true, + unused: true, + } + input: { + console.log(function() { + function f() {} + return ++f; + }()); + } + expect: { + console.log(NaN); + } + expect_stdout: "NaN" +} + unsafe_evaluate_side_effect_free_1: { options = { evaluate: true, |