From 87bae623e9d0cf0ad430aeb732be95094fc4c6e6 Mon Sep 17 00:00:00 2001 From: "Alex Lam S.L" Date: Mon, 4 Dec 2017 00:18:48 +0800 Subject: [PATCH] simplify computed properties for methods, getters & setters (#2555) fixes #2554 --- lib/compress.js | 37 +++++--- test/compress/object.js | 201 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 226 insertions(+), 12 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index af13c716..1c02bfc7 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -5341,7 +5341,31 @@ merge(Compressor.prototype, { return self; }); + // ["p"]:1 ---> p:1 + // [42]:1 ---> 42:1 + function lift_key(self, compressor) { + if (!compressor.option("computed_props")) return self; + // save a comparison in the typical case + if (!(self.key instanceof AST_Constant)) return self; + // whitelist acceptable props as not all AST_Constants are true constants + if (self.key instanceof AST_String || self.key instanceof AST_Number) { + if (self.key.value == "constructor" + && compressor.parent() instanceof AST_Class) return self; + if (self instanceof AST_ObjectKeyVal) { + self.key = self.key.value; + } else { + self.key = make_node(AST_SymbolMethod, self.key, { + name: self.key.value + }); + } + } + return self; + } + + OPT(AST_ObjectProperty, lift_key); + OPT(AST_ConciseMethod, function(self, compressor){ + lift_key(self, compressor); // p(){return x;} ---> p:()=>x if (compressor.option("arrows") && compressor.parent() instanceof AST_Object @@ -5362,18 +5386,7 @@ merge(Compressor.prototype, { }); OPT(AST_ObjectKeyVal, function(self, compressor){ - // ["p"]:1 ---> p:1 - // [42]:1 ---> 42:1 - if (compressor.option("computed_props") - && self.key instanceof AST_Constant // save a comparison in the typical case - && ( - // whitelist acceptable props as not all AST_Constants are true constants - self.key instanceof AST_String - || self.key instanceof AST_Number - )) { - self.key = self.key.value; - // fallthrough - `return self` not needed as transformed tree in good form - } + lift_key(self, compressor); // p:function(){} ---> p(){} // p:function*(){} ---> *p(){} // p:async function(){} ---> async p(){} diff --git a/test/compress/object.js b/test/compress/object.js index 6e0737df..fbf24494 100644 --- a/test/compress/object.js +++ b/test/compress/object.js @@ -812,3 +812,204 @@ prop_arrow_with_nested_this: { ] node_version: ">=4" } + +issue_2554_1: { + options = { + computed_props: true, + evaluate: true, + } + input: { + var obj = { + ["x" + ""]: 1, + ["method" + ""]() { + this.s = "PASS"; + }, + get ["g" + ""]() { + return this.x; + }, + set ["s" + ""](value) { + this.x = value; + } + }; + obj.method(); + console.log(obj.g); + } + expect: { + var obj = { + x: 1, + method() { + this.s = "PASS"; + }, + get g() { + return this.x; + }, + set s(value) { + this.x = value; + } + }; + obj.method(); + console.log(obj.g); + } + expect_stdout: "PASS" + node_version: ">=4" +} + +issue_2554_2: { + options = { + computed_props: true, + evaluate: true, + } + input: { + var instance = new class { + constructor() { + this.x = 2; + } + ["method" + ""]() { + this.s = "PASS"; + } + get ["g" + ""]() { + return this.x; + } + set ["s" + ""](value) { + this.x = value; + } + }(); + instance.method(); + console.log(instance.g); + } + expect: { + var instance = new class { + constructor() { + this.x = 2; + } + method() { + this.s = "PASS"; + } + get g() { + return this.x; + } + set s(value) { + this.x = value; + } + }(); + instance.method(); + console.log(instance.g); + } + expect_stdout: "PASS" + node_version: ">=6" +} + +issue_2554_3: { + options = { + computed_props: true, + evaluate: true, + } + input: { + var foo = { + [1 + 0]: 1, + [2 + 0]() { + this[4] = "PASS"; + }, + get [3 + 0]() { + return this[1]; + }, + set [4 + 0](value) { + this[1] = value; + } + }; + foo[2](); + console.log(foo[3]); + } + expect: { + var foo = { + 1: 1, + 2() { + this[4] = "PASS"; + }, + get 3() { + return this[1]; + }, + set 4(value) { + this[1] = value; + } + }; + foo[2](); + console.log(foo[3]); + } + expect_stdout: "PASS" + node_version: ">=4" +} + +issue_2554_4: { + options = { + computed_props: true, + evaluate: true, + } + input: { + var bar = new class { + constructor() { + this[1] = 2; + } + [2 + 0]() { + this[4] = "PASS"; + } + get [3 + 0]() { + return this[1]; + } + set [4 + 0](value) { + this[1] = value; + } + }(); + bar[2](); + console.log(bar[3]); + } + expect: { + var bar = new class { + constructor() { + this[1] = 2; + } + 2() { + this[4] = "PASS"; + } + get 3() { + return this[1]; + } + set 4(value) { + this[1] = value; + } + }(); + bar[2](); + console.log(bar[3]); + } + expect_stdout: "PASS" + node_version: ">=6" +} + +issue_2554_5: { + options = { + computed_props: true, + evaluate: true, + } + input: { + new class { + ["constructor"]() { + console.log("FAIL"); + } + "constructor"() { + console.log("PASS"); + } + }(); + } + expect: { + new class { + ["constructor"]() { + console.log("FAIL"); + } + constructor() { + console.log("PASS"); + } + }(); + } + expect_stdout: "PASS" + node_version: ">=6" +}