From 423d0146be1e17b11cb8270ab9d32c8550b5bd00 Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Fri, 23 Feb 2018 00:28:59 +0800 Subject: [PATCH] no `base54.reset()` slightly less improved gzip results --- lib/scope.js | 104 ++++++++++++++++++++--------------- test/compress/group_voids.js | 50 ++++++++--------- 2 files changed, 83 insertions(+), 71 deletions(-) diff --git a/lib/scope.js b/lib/scope.js index f9880a4f..09807d57 100644 --- a/lib/scope.js +++ b/lib/scope.js @@ -458,17 +458,14 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){ this.walk(tw); to_mangle.forEach(function(def){ def.mangle(options) }); - if (options.group_voids) { - base54.reset(); - base54.sort(); - if (options.toplevel) this.group_voids(options); - else this.walk(new TreeWalker(function(node) { - if (node instanceof AST_Scope && !(node instanceof AST_Toplevel)) { - node.group_voids(options); - return true; - } - })); - } + if (!options.group_voids) return; + if (options.toplevel) this.group_voids(options); + else this.walk(new TreeWalker(function(node) { + if (node instanceof AST_Scope && !(node instanceof AST_Toplevel)) { + node.group_voids(options); + return true; + } + })); function collect(symbol) { if (!member(symbol.name, options.reserved)) { @@ -477,11 +474,11 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){ } }); -AST_Scope.DEFMETHOD("find_colliding_names", function(options, all) { +AST_Toplevel.DEFMETHOD("find_colliding_names", function(options) { var cache = options.cache && options.cache.props; var avoid = Object.create(null); options.reserved.forEach(to_avoid); - if (this.globals) this.globals.each(add_def); + this.globals.each(add_def); this.walk(new TreeWalker(function(node) { if (node instanceof AST_Scope) node.variables.each(add_def); if (node instanceof AST_SymbolCatch) add_def(node.definition()); @@ -493,9 +490,9 @@ AST_Scope.DEFMETHOD("find_colliding_names", function(options, all) { } function add_def(def) { - var name = def.mangled_name || def.name; + var name = def.name; if (def.global && cache && cache.has(name)) name = cache.get(name); - else if (!all && !def.unmangleable(options)) return; + else if (!def.unmangleable(options)) return; to_avoid(name); } }); @@ -536,39 +533,56 @@ AST_Toplevel.DEFMETHOD("expand_names", function(options) { }); AST_Scope.DEFMETHOD("group_voids", function(options) { - var avoid = this.find_colliding_names(options, true); - var cname = 0; - var name; - do { - name = base54(cname++); - } while (avoid[name] || !is_identifier(name)); - var count = 0; - this.transform(new TreeTransformer(function(node) { - if (node instanceof AST_Undefined - || node instanceof AST_UnaryPrefix - && node.operator == "void" - && node.expression.is_constant()) { - count++; - return new AST_SymbolRef({ - name: name, - start: node.start, - end: node.end - }); + var self = this, enclosed = []; + var scopes = [], count = 0; + self.walk(new TreeWalker(function(node, descend) { + if (node instanceof AST_Scope && node !== self) { + scopes.unshift(node); + descend(); + if (scopes[0] === node) scopes.shift(); + return true; } - })); - if (count) { - for (var i = 0, len = this.body.length; i < len; i++) { - var stat = this.body[i]; - if (stat instanceof AST_Var) { - stat.definitions.push(make_var_def(stat)); - return; + if (count > 0 && scopes.length == 0) return; + if (is_undefined(node)) { + count++; + var scope; + while (scope = scopes.shift()) { + scope.enclosed.forEach(function(def) { + push_uniq(enclosed, def); + }); } } - this.body.push(new AST_Var({ - definitions: [ make_var_def(this) ], - start: this.start, - end: this.end - })); + })); + if (count < 1) return; + var save = self.enclosed; + self.enclosed = enclosed; + var name = next_mangled(self, options); + self.enclosed = save; + this.transform(new TreeTransformer(function(node) { + if (is_undefined(node)) return new AST_SymbolRef({ + name: name, + start: node.start, + end: node.end + }); + })); + for (var i = 0, len = this.body.length; i < len; i++) { + var stat = this.body[i]; + if (stat instanceof AST_Var) { + stat.definitions.push(make_var_def(stat)); + return; + } + } + this.body.push(new AST_Var({ + definitions: [ make_var_def(this) ], + start: this.start, + end: this.end + })); + + function is_undefined(node) { + return node instanceof AST_Undefined + || node instanceof AST_UnaryPrefix + && node.operator == "void" + && node.expression.is_constant(); } function make_var_def(node) { diff --git a/test/compress/group_voids.js b/test/compress/group_voids.js index 2d960079..1eedcfa9 100644 --- a/test/compress/group_voids.js +++ b/test/compress/group_voids.js @@ -26,13 +26,13 @@ group_voids: { console.log(void 0); for (var a = 4;;); var b = 4; - function f5() { + function g() { var c = 5; var d = 5; console.log(void 0); } } - function f6() { + function f5() { try { var a = 6; console.log(void 0); @@ -47,35 +47,35 @@ group_voids: { if (void 0 === b) c = void 0; function f1() { - var o = 1, a; - console.log(a); + var o = 1, n; + console.log(n); } function f2(o) { - var n = 2, a; - console.log(a); + var n = 2, v; + console.log(v); } function f3() { - var o = 3, a; - console.log(a); + var o = 3, n; + console.log(n); } function f4() { - console.log(a); + console.log(i); for(var o = 4;;); - var n = 4, a; + var n = 4, i; function v() { var o = 5; var n = 5; - console.log(a); + console.log(i); } } - function f6() { + function f5() { try { var o = 6; - console.log(a); + console.log(n); } catch (o) { - console.log(a); + console.log(n); } - var a; + var n; } } } @@ -108,13 +108,13 @@ group_voids_toplevel: { console.log(void 0); for (var a = 4;;); var b = 4; - function f5() { + function g() { var c = 5; var d = 5; console.log(void 0); } } - function f6() { + function f5() { try { var a = 6; console.log(void 0); @@ -168,8 +168,7 @@ group_voids_catch: { group_voids: true, } input: { - f(); - function f() { + (function() { var a = 1; console.log(void 0); try { @@ -177,19 +176,18 @@ group_voids_catch: { } catch (undefined) { console.log(void 0); } - } + })(); } expect: { - f(); - function f() { - var o = 1, a; - console.log(a); + (function() { + var o = 1, c; + console.log(c); try { throw "FAIL"; } catch (o) { - console.log(a); + console.log(c); } - } + })(); } expect_stdout: [ "undefined",