From 100307ab31e89075a5b0e56d47597a0525dd43a6 Mon Sep 17 00:00:00 2001 From: alexlamsl Date: Sat, 18 Feb 2017 19:05:11 +0800 Subject: [PATCH] fixes & improvements to [].join() fixes - [a].join() => "" + a - ["a", , "b"].join() => "a,,b" - ["a", null, "b"].join() => "a,,b" - ["a", undefined, "b"].join() => "a,,b" improvements - ["a", "b"].join(null) => "anullb" - ["a", "b"].join(undefined) => "a,b" - [a + "b", c].join("") => a + "b" + c closes #1453 --- lib/compress.js | 62 ++++++++++++++++++++++++++--------------- test/compress/arrays.js | 53 +++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 23 deletions(-) diff --git a/lib/compress.js b/lib/compress.js index 0dcfb2ba..2ba2982e 100644 --- a/lib/compress.js +++ b/lib/compress.js @@ -2290,39 +2290,57 @@ merge(Compressor.prototype, { }).transform(compressor); } else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: { - var separator = self.args.length == 0 ? "," : self.args[0].evaluate(compressor)[1]; - if (separator == null) break EXIT; // not a constant - var elements = exp.expression.elements.reduce(function(a, el){ + var separator; + if (self.args.length > 0) { + separator = self.args[0].evaluate(compressor); + if (separator.length < 2) break EXIT; // not a constant + separator = separator[1]; + } + var elements = []; + var consts = []; + exp.expression.elements.forEach(function(el) { el = el.evaluate(compressor); - if (a.length == 0 || el.length == 1) { - a.push(el); + if (el.length > 1) { + consts.push(el[1]); } else { - var last = a[a.length - 1]; - if (last.length == 2) { - // it's a constant - var val = "" + last[1] + separator + el[1]; - a[a.length - 1] = [ make_node_from_constant(compressor, val, last[0]), val ]; - } else { - a.push(el); + if (consts.length > 0) { + elements.push(make_node(AST_String, self, { + value: consts.join(separator) + })); + consts.length = 0; } + elements.push(el[0]); } - return a; - }, []); + }); + if (consts.length > 0) { + elements.push(make_node(AST_String, self, { + value: consts.join(separator) + })); + } if (elements.length == 0) return make_node(AST_String, self, { value: "" }); - if (elements.length == 1) return elements[0][0]; + if (elements.length == 1) { + if (elements[0].is_string(compressor)) { + return elements[0]; + } + return make_node(AST_Binary, elements[0], { + operator : "+", + left : make_node(AST_String, self, { value: "" }), + right : elements[0] + }); + } if (separator == "") { var first; - if (elements[0][0] instanceof AST_String - || elements[1][0] instanceof AST_String) { - first = elements.shift()[0]; + if (elements[0].is_string(compressor) + || elements[1].is_string(compressor)) { + first = elements.shift(); } else { first = make_node(AST_String, self, { value: "" }); } return elements.reduce(function(prev, el){ - return make_node(AST_Binary, el[0], { + return make_node(AST_Binary, el, { operator : "+", left : prev, - right : el[0], + right : el }); }, first).transform(compressor); } @@ -2331,9 +2349,7 @@ merge(Compressor.prototype, { var node = self.clone(); node.expression = node.expression.clone(); node.expression.expression = node.expression.expression.clone(); - node.expression.expression.elements = elements.map(function(el){ - return el[0]; - }); + node.expression.expression.elements = elements; return best_of(self, node); } } diff --git a/test/compress/arrays.js b/test/compress/arrays.js index 77ef761a..2e1f86ed 100644 --- a/test/compress/arrays.js +++ b/test/compress/arrays.js @@ -21,10 +21,19 @@ constant_join: { input: { var a = [ "foo", "bar", "baz" ].join(""); var a1 = [ "foo", "bar", "baz" ].join(); + var a2 = [ "foo", "bar", "baz" ].join(null); + var a3 = [ "foo", "bar", "baz" ].join(void 0); + var a4 = [ "foo", , "baz" ].join(); + var a5 = [ "foo", null, "baz" ].join(); + var a6 = [ "foo", void 0, "baz" ].join(); var b = [ "foo", 1, 2, 3, "bar" ].join(""); var c = [ boo(), "foo", 1, 2, 3, "bar", bar() ].join(""); var c1 = [ boo(), bar(), "foo", 1, 2, 3, "bar", bar() ].join(""); var c2 = [ 1, 2, "foo", "bar", baz() ].join(""); + var c3 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join(""); + var c4 = [ 1, 2, null, undefined, "foo", "bar", baz() ].join(""); + var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join(); + var c6 = [ 1, 2, null, undefined, "foo", "bar", baz() ].join(); var d = [ "foo", 1 + 2 + "bar", "baz" ].join("-"); var e = [].join(foo + bar); var f = [].join(""); @@ -33,10 +42,19 @@ constant_join: { expect: { var a = "foobarbaz"; var a1 = "foo,bar,baz"; + var a2 = "foonullbarnullbaz"; + var a3 = "foo,bar,baz"; + var a4 = "foo,,baz"; + var a5 = "foo,,baz"; + var a6 = "foo,,baz"; var b = "foo123bar"; var c = boo() + "foo123bar" + bar(); var c1 = "" + boo() + bar() + "foo123bar" + bar(); var c2 = "12foobar" + baz(); + var c3 = boo() + bar() + "foo123bar" + (bar() + "foo"); + var c4 = "12foobar" + baz(); + var c5 = [ boo() + bar() + "foo", 1, 2, 3, "bar", bar() + "foo" ].join(); + var c6 = [ "1,2,,,foo,bar", baz() ].join(); var d = "foo-3bar-baz"; var e = [].join(foo + bar); var f = ""; @@ -73,6 +91,41 @@ constant_join_2: { } } +constant_join_3: { + options = { + unsafe: true, + evaluate: true, + }; + input: { + var a = [ null ].join(); + var b = [ , ].join(); + var c = [ , 1, , 3 ].join(); + var d = [ foo ].join(); + var e = [ foo, null, undefined, bar ].join("-"); + var f = [ foo, bar ].join(""); + var g = [ null, "foo", null, bar + "baz" ].join(""); + var h = [ null, "foo", null, bar + "baz" ].join("-"); + var i = [ "foo" + bar, null, baz + "moo" ].join(""); + var j = [ foo + "bar", baz ].join(""); + var k = [ foo, "bar" + baz ].join(""); + var l = [ foo, bar + "baz" ].join(""); + } + expect: { + var a = ""; + var b = ""; + var c = ",1,,3"; + var d = "" + foo; + var e = [ foo, "-", bar ].join("-"); + var f = "" + foo + bar; + var g = "foo" + (bar + "baz"); + var h = [ "-foo-", bar + "baz" ].join("-"); + var i = "foo" + bar + (baz + "moo"); + var j = foo + "bar" + baz; + var k = foo + ("bar" + baz); + var l = foo + (bar + "baz"); + } +} + for_loop: { options = { unsafe : true, -- 2.34.1