From 3344baac195e00ee03280033cf70755d5c3924ab Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Thu, 27 Oct 2016 14:50:59 -0400 Subject: [PATCH 01/15] Simplify assignments to same identifier --- .../__tests__/simplify-test.js | 48 +++++++++++++++++ .../babel-plugin-minify-simplify/src/index.js | 53 +++++++++++++++++++ 2 files changed, 101 insertions(+) diff --git a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js index d9f607848..d20535b12 100644 --- a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js +++ b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js @@ -2136,4 +2136,52 @@ describe("simplify-plugin", () => { const expected = source; expect(transform(source)).toBe(expected); }); + + it("should transform assignments to the same identifier", () => { + const source = unpad(` + x = x + 1; + x = x - 1; + x = x * 1; + x = x % 1; + x = x << 1; + x = x >> 1; + x = x >>> 1; + x = x & 1; + x = x | 1; + x = x ^ 1; + x = x / 1; + x = x ** 1; + foo = foo + bar; + foo = foo * function(){}; + foo += 123; + foo = 1 + foo; + x = x = x + 1; + foo = foo + bar + baz; + window.foo = window.foo + 1; + window.foo.bar = window.foo.baz + 1; + `); + const expected = unpad(` + x++, + x--, + x *= 1, + x %= 1, + x <<= 1, + x >>= 1, + x >>>= 1, + x &= 1, + x |= 1, + x ^= 1, + x /= 1, + x **= 1, + foo += bar, + foo *= function () {}, + foo += 123, + foo = 1 + foo, + x = x++, + foo = foo + bar + baz, + window.foo = window.foo + 1, + window.foo.bar = window.foo.baz + 1; + `); + expect(transform(source)).toBe(expected); + }); }); diff --git a/packages/babel-plugin-minify-simplify/src/index.js b/packages/babel-plugin-minify-simplify/src/index.js index a18d5d2de..04f6df991 100644 --- a/packages/babel-plugin-minify-simplify/src/index.js +++ b/packages/babel-plugin-minify-simplify/src/index.js @@ -28,6 +28,17 @@ module.exports = ({ types: t }) => { const or = (a, b) => t.logicalExpression("||", a, b); const and = (a, b) => t.logicalExpression("&&", a, b); + const operators = new Set([ + '+', '-', '*', '%', + '<<', '>>', '>>>', + '&', '|', '^', '/', + '**' + ]); + + const updateOperators = new Set([ + '+', '-' + ]); + return { name: "minify-simplify", visitor: { @@ -124,6 +135,48 @@ module.exports = ({ types: t }) => { ], }, + AssignmentExpression(path) { + + const right = path.get('right'); + const left = path.get('left'); + + const canShorten = ( + right.type === 'BinaryExpression' && + operators.has(right.node.operator) && + left.node.name === right.node.left.name + ); + + if (!canShorten) return; + + const canBeUpdateExpression = ( + right.node.right.type === 'NumericLiteral' && + right.node.right.value === 1 && + updateOperators.has(right.node.operator)); + + if (left.node.name === undefined) { + // not an identifier, probably MemberExpression which we don't transform yet + return; + } + + if (canBeUpdateExpression) { + + const newExpression = t.updateExpression( + right.node.operator + right.node.operator, + t.identifier(left.node.name)); + + path.replaceWith(newExpression); + } + else { + + const newExpression = t.assignmentExpression( + right.node.operator + '=', + t.identifier(left.node.name), + t.clone(right.node.right)); + + path.replaceWith(newExpression); + } + }, + ConditionalExpression: { enter: [ // !foo ? 'foo' : 'bar' -> foo ? 'bar' : 'foo' From a4d10bc6e83da853ca2231065e6c0d1c9bbd8e6a Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Thu, 27 Oct 2016 14:57:18 -0400 Subject: [PATCH 02/15] Add tests --- .../__tests__/simplify-test.js | 95 ++++++++++--------- .../babel-plugin-minify-simplify/src/index.js | 3 +- 2 files changed, 52 insertions(+), 46 deletions(-) diff --git a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js index d20535b12..f9ce1649a 100644 --- a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js +++ b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js @@ -2138,50 +2138,55 @@ describe("simplify-plugin", () => { }); it("should transform assignments to the same identifier", () => { - const source = unpad(` - x = x + 1; - x = x - 1; - x = x * 1; - x = x % 1; - x = x << 1; - x = x >> 1; - x = x >>> 1; - x = x & 1; - x = x | 1; - x = x ^ 1; - x = x / 1; - x = x ** 1; - foo = foo + bar; - foo = foo * function(){}; - foo += 123; - foo = 1 + foo; - x = x = x + 1; - foo = foo + bar + baz; - window.foo = window.foo + 1; - window.foo.bar = window.foo.baz + 1; - `); - const expected = unpad(` - x++, - x--, - x *= 1, - x %= 1, - x <<= 1, - x >>= 1, - x >>>= 1, - x &= 1, - x |= 1, - x ^= 1, - x /= 1, - x **= 1, - foo += bar, - foo *= function () {}, - foo += 123, - foo = 1 + foo, - x = x++, - foo = foo + bar + baz, - window.foo = window.foo + 1, - window.foo.bar = window.foo.baz + 1; - `); - expect(transform(source)).toBe(expected); + + const actual = [ + 'x = x + 1;', + 'x = x - 1;', + 'x = x * 1;', + 'x = x % 1;', + 'x = x << 1;', + 'x = x >> 1;', + 'x = x >>> 1;', + 'x = x & 1;', + 'x = x | 1;', + 'x = x ^ 1;', + 'x = x / 1;', + 'x = x ** 1;', + 'foo = foo + bar;', + 'foo = foo * function(){};', + 'foo += 123;', + 'foo = 1 + foo;', + 'x = x = x + 1;', + 'foo = foo + bar + baz;', + 'window.foo = window.foo + 1;', + 'window.foo.bar = window.foo.baz + 1;', + ]; + + const expected = [ + 'x++;', + 'x--;', + 'x *= 1;', + 'x %= 1;', + 'x <<= 1;', + 'x >>= 1;', + 'x >>>= 1;', + 'x &= 1;', + 'x |= 1;', + 'x ^= 1;', + 'x /= 1;', + 'x **= 1;', + 'foo += bar;', + 'foo *= function () {};', + 'foo += 123;', + 'foo = 1 + foo;', + 'x = x++;', + 'foo = foo + bar + baz;', + 'window.foo = window.foo + 1;', + 'window.foo.bar = window.foo.baz + 1;', + ]; + + actual.forEach((test, index) => { + expect(transform(test)).toBe(expected[index]); + }); }); }); diff --git a/packages/babel-plugin-minify-simplify/src/index.js b/packages/babel-plugin-minify-simplify/src/index.js index 04f6df991..b0095d6a5 100644 --- a/packages/babel-plugin-minify-simplify/src/index.js +++ b/packages/babel-plugin-minify-simplify/src/index.js @@ -154,7 +154,8 @@ module.exports = ({ types: t }) => { updateOperators.has(right.node.operator)); if (left.node.name === undefined) { - // not an identifier, probably MemberExpression which we don't transform yet + // TODO: transform MemberExpressions as well + // e.g. foo.bar = foo.bar + 123; return; } From c666da10e995c28d3fac93b2ca57dfabc5168de6 Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Thu, 27 Oct 2016 14:58:00 -0400 Subject: [PATCH 03/15] Bump versions --- packages/babel-plugin-minify-simplify/package.json | 2 +- packages/babel-preset-babili/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/babel-plugin-minify-simplify/package.json b/packages/babel-plugin-minify-simplify/package.json index deeffe27d..c7a0ab7ad 100644 --- a/packages/babel-plugin-minify-simplify/package.json +++ b/packages/babel-plugin-minify-simplify/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-minify-simplify", - "version": "0.0.3", + "version": "0.0.4", "description": "", "homepage": "https://github.com/babel/babili#readme", "repository": "https://github.com/babel/babili/tree/master/packages/babel-plugin-minify-simplify", diff --git a/packages/babel-preset-babili/package.json b/packages/babel-preset-babili/package.json index 362a45502..fa9f0db26 100644 --- a/packages/babel-preset-babili/package.json +++ b/packages/babel-preset-babili/package.json @@ -20,7 +20,7 @@ "babel-plugin-minify-mangle-names": "^0.0.3", "babel-plugin-minify-numeric-literals": "^0.0.1", "babel-plugin-minify-replace": "^0.0.1", - "babel-plugin-minify-simplify": "^0.0.3", + "babel-plugin-minify-simplify": "^0.0.4", "babel-plugin-minify-type-constructors": "^0.0.1", "babel-plugin-transform-member-expression-literals": "^6.8.0", "babel-plugin-transform-merge-sibling-variables": "^6.8.0", From c6ec99d7e34882eac99ed201fca800c4dc16d217 Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Thu, 27 Oct 2016 15:03:48 -0400 Subject: [PATCH 04/15] Remove versioning --- packages/babel-preset-babili/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/babel-preset-babili/package.json b/packages/babel-preset-babili/package.json index fa9f0db26..362a45502 100644 --- a/packages/babel-preset-babili/package.json +++ b/packages/babel-preset-babili/package.json @@ -20,7 +20,7 @@ "babel-plugin-minify-mangle-names": "^0.0.3", "babel-plugin-minify-numeric-literals": "^0.0.1", "babel-plugin-minify-replace": "^0.0.1", - "babel-plugin-minify-simplify": "^0.0.4", + "babel-plugin-minify-simplify": "^0.0.3", "babel-plugin-minify-type-constructors": "^0.0.1", "babel-plugin-transform-member-expression-literals": "^6.8.0", "babel-plugin-transform-merge-sibling-variables": "^6.8.0", From 6b913fe007af4c20510067a9922adc282fee47df Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Thu, 27 Oct 2016 16:46:21 -0400 Subject: [PATCH 05/15] Remove version --- packages/babel-plugin-minify-simplify/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/babel-plugin-minify-simplify/package.json b/packages/babel-plugin-minify-simplify/package.json index c7a0ab7ad..deeffe27d 100644 --- a/packages/babel-plugin-minify-simplify/package.json +++ b/packages/babel-plugin-minify-simplify/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-minify-simplify", - "version": "0.0.4", + "version": "0.0.3", "description": "", "homepage": "https://github.com/babel/babili#readme", "repository": "https://github.com/babel/babili/tree/master/packages/babel-plugin-minify-simplify", From c1aa0caf98e7ec4ff339777cb9240019ad13a3c4 Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Mon, 31 Oct 2016 20:50:23 -0400 Subject: [PATCH 06/15] Add support for optimizing member expressions --- .../__tests__/simplify-test.js | 167 ++++++++++++------ .../babel-plugin-minify-simplify/src/index.js | 111 +++++++++--- 2 files changed, 199 insertions(+), 79 deletions(-) diff --git a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js index f9ce1649a..4450e4f03 100644 --- a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js +++ b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js @@ -2137,56 +2137,121 @@ describe("simplify-plugin", () => { expect(transform(source)).toBe(expected); }); - it("should transform assignments to the same identifier", () => { - - const actual = [ - 'x = x + 1;', - 'x = x - 1;', - 'x = x * 1;', - 'x = x % 1;', - 'x = x << 1;', - 'x = x >> 1;', - 'x = x >>> 1;', - 'x = x & 1;', - 'x = x | 1;', - 'x = x ^ 1;', - 'x = x / 1;', - 'x = x ** 1;', - 'foo = foo + bar;', - 'foo = foo * function(){};', - 'foo += 123;', - 'foo = 1 + foo;', - 'x = x = x + 1;', - 'foo = foo + bar + baz;', - 'window.foo = window.foo + 1;', - 'window.foo.bar = window.foo.baz + 1;', - ]; - - const expected = [ - 'x++;', - 'x--;', - 'x *= 1;', - 'x %= 1;', - 'x <<= 1;', - 'x >>= 1;', - 'x >>>= 1;', - 'x &= 1;', - 'x |= 1;', - 'x ^= 1;', - 'x /= 1;', - 'x **= 1;', - 'foo += bar;', - 'foo *= function () {};', - 'foo += 123;', - 'foo = 1 + foo;', - 'x = x++;', - 'foo = foo + bar + baz;', - 'window.foo = window.foo + 1;', - 'window.foo.bar = window.foo.baz + 1;', - ]; - - actual.forEach((test, index) => { - expect(transform(test)).toBe(expected[index]); - }); + it("should simplify assignments", () => { + + const source = unpad(` + x = x + 1, + x = x - 1, + x = x * 1, + x = x % 1, + x = x << 1, + x = x >> 1, + x = x >>> 1, + x = x & 1, + x = x | 1, + x = x ^ 1, + x = x / 1, + x = x ** 1; + `); + const expected = unpad(` + x++, + x--, + x *= 1, + x %= 1, + x <<= 1, + x >>= 1, + x >>>= 1, + x &= 1, + x |= 1, + x ^= 1, + x /= 1, + x **= 1; + `).replace(/\s+/g, ' '); + + expect(transform(source)).toBe(expected); + }); + + it("should simplify assignments 2", () => { + + const source = unpad(` + foo = foo + bar, + foo = foo * function(){}, + foo += 123, + foo = 1 + foo, + x = x = x + 1, + foo = foo + bar + baz + `); + const expected = unpad(` + foo += bar, + foo *= function () {}, + foo += 123, + foo = 1 + foo, + x = x++, + foo = foo + bar + baz; + `).replace(/\s+/g, ' '); + + expect(transform(source)).toBe(expected); + }); + + it("should simplify assignments w. member expressions", () => { + + const source = unpad(` + foo.bar = foo.bar + 1, + foo.bar = foo.bar + 2, + foo["x"] = foo[x] + 2, + foo[x] = foo[x] + 2, + foo[x] = foo["x"] + 2, + foo["x"] = foo["x"] + 2, + foo[1] = foo["1"] + 2, + foo["bar"] = foo["bar"] + 2, + foo[bar()] = foo[bar()] + 2, + foo[""] = foo[""] + 2, + foo[2] = foo[2] + 2, + foo[{}] = foo[{}] + 1, + foo[function(){}] = foo[function(){}] + 1, + foo[false] = foo[false] + 1, + foo.bar.baz = foo.bar.baz + 321, + this.hello = this.hello + 1; + `); + const expected = unpad(` + foo.bar++, + foo.bar += 2, + foo["x"] = foo[x] + 2, + foo[x] += 2, + foo[x] = foo["x"] + 2, + foo["x"] += 2, + foo[1] += 2, + foo["bar"] += 2, + foo[bar()] = foo[bar()] + 2, + foo[""] += 2, + foo[2] += 2, + foo[{}] = foo[{}] + 1, + foo[function () {}] = foo[function () {}] + 1, + foo[false]++, + foo.bar.baz += 321, + this.hello++; + `).replace(/\s+/g, ' '); + + expect(transform(source)).toBe(expected); + }); + + it("should simplify assignments w. member expressions", () => { + + const source = unpad(` + class Foo { + foo() { + super.foo = super.foo + 1; + } + }; + `); + const expected = unpad(` + class Foo { + foo() { + super.foo++; + } + }; + `); + + expect(transform(source)).toBe(expected); }); }); diff --git a/packages/babel-plugin-minify-simplify/src/index.js b/packages/babel-plugin-minify-simplify/src/index.js index b0095d6a5..ee9d8b85c 100644 --- a/packages/babel-plugin-minify-simplify/src/index.js +++ b/packages/babel-plugin-minify-simplify/src/index.js @@ -39,6 +39,51 @@ module.exports = ({ types: t }) => { '+', '-' ]); + function isEqual(arr1, arr2) { + return arr1.every((value, index) => { + return value.toString() === arr2[index].toString(); + }); + } + + function getName(node) { + if (node.type === 'ThisExpression') { + return 'this'; + } + if (node.type === 'Super') { + return 'super'; + } + // augment identifiers so that they don't match + // string/number literals + // but still match against each other + return node.name + ? node.name + '_' + : node.value /* Literal */; + } + + function getPropNames(path) { + if (!path.isMemberExpression()) { + return; + } + + let obj = path.get('object'); + + const prop = path.get('property'); + const propNames = [getName(prop.node)]; + + while (obj.type !== 'Identifier' && + obj.type !== 'ThisExpression' && + obj.type !== 'Super') { + const node = obj.get('property').node; + if (node) { + propNames.push(getName(node)); + } + obj = obj.get('object'); + } + propNames.push(getName(obj.node)); + + return propNames; + } + return { name: "minify-simplify", visitor: { @@ -137,45 +182,55 @@ module.exports = ({ types: t }) => { AssignmentExpression(path) { - const right = path.get('right'); - const left = path.get('left'); - - const canShorten = ( - right.type === 'BinaryExpression' && - operators.has(right.node.operator) && - left.node.name === right.node.left.name - ); - - if (!canShorten) return; + const rightExpr = path.get('right'); + const leftExpr = path.get('left'); const canBeUpdateExpression = ( - right.node.right.type === 'NumericLiteral' && - right.node.right.value === 1 && - updateOperators.has(right.node.operator)); + rightExpr.get('right').isNumericLiteral() && + rightExpr.get('right').node.value === 1 && + updateOperators.has(rightExpr.node.operator)); - if (left.node.name === undefined) { - // TODO: transform MemberExpressions as well - // e.g. foo.bar = foo.bar + 123; - return; - } + if (leftExpr.isMemberExpression()) { - if (canBeUpdateExpression) { + const leftPropNames = getPropNames(leftExpr); + const rightPropNames = getPropNames(rightExpr.get('left')); - const newExpression = t.updateExpression( - right.node.operator + right.node.operator, - t.identifier(left.node.name)); + if (!leftPropNames || + leftPropNames.includes(undefined) || + !rightPropNames || + rightPropNames.includes(undefined) || + !isEqual(leftPropNames, rightPropNames)) { + return; + } - path.replaceWith(newExpression); + // TODO: implement replacement } else { + if (!rightExpr.isBinaryExpression() || + !operators.has(rightExpr.node.operator) || + leftExpr.node.name !== rightExpr.node.left.name) { + return; + } + } - const newExpression = t.assignmentExpression( - right.node.operator + '=', - t.identifier(left.node.name), - t.clone(right.node.right)); + let newExpression; - path.replaceWith(newExpression); + // special case +=1 --> ++ + if (canBeUpdateExpression) { + newExpression = t.updateExpression( + rightExpr.node.operator + rightExpr.node.operator, + leftExpr.isMemberExpression() + ? t.clone(leftExpr.node) + : t.identifier(leftExpr.node.name)); } + else { + newExpression = t.assignmentExpression( + rightExpr.node.operator + '=', + t.clone(leftExpr.node), + t.clone(rightExpr.node.right)); + } + + path.replaceWith(newExpression); }, ConditionalExpression: { From 6dfe2186a3abee90ad7a0af0b5b774dbf6690d38 Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Mon, 31 Oct 2016 20:51:36 -0400 Subject: [PATCH 07/15] Fix test name --- .../babel-plugin-minify-simplify/__tests__/simplify-test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js index 4450e4f03..17b1487d7 100644 --- a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js +++ b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js @@ -2235,7 +2235,7 @@ describe("simplify-plugin", () => { expect(transform(source)).toBe(expected); }); - it("should simplify assignments w. member expressions", () => { + it("should simplify assignments w. super", () => { const source = unpad(` class Foo { From 6813842a55fccf4ee044b2bcc0858ff752fe95c2 Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Mon, 31 Oct 2016 20:55:09 -0400 Subject: [PATCH 08/15] Remove comment --- packages/babel-plugin-minify-simplify/src/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/babel-plugin-minify-simplify/src/index.js b/packages/babel-plugin-minify-simplify/src/index.js index ee9d8b85c..c96147869 100644 --- a/packages/babel-plugin-minify-simplify/src/index.js +++ b/packages/babel-plugin-minify-simplify/src/index.js @@ -202,8 +202,6 @@ module.exports = ({ types: t }) => { !isEqual(leftPropNames, rightPropNames)) { return; } - - // TODO: implement replacement } else { if (!rightExpr.isBinaryExpression() || From 5ddc5f8b70672969f59ddb1f2f97c25545b06306 Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Mon, 31 Oct 2016 20:55:54 -0400 Subject: [PATCH 09/15] Simplify ternary --- packages/babel-plugin-minify-simplify/src/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/babel-plugin-minify-simplify/src/index.js b/packages/babel-plugin-minify-simplify/src/index.js index c96147869..c04557cf4 100644 --- a/packages/babel-plugin-minify-simplify/src/index.js +++ b/packages/babel-plugin-minify-simplify/src/index.js @@ -217,9 +217,7 @@ module.exports = ({ types: t }) => { if (canBeUpdateExpression) { newExpression = t.updateExpression( rightExpr.node.operator + rightExpr.node.operator, - leftExpr.isMemberExpression() - ? t.clone(leftExpr.node) - : t.identifier(leftExpr.node.name)); + t.clone(leftExpr.node)); } else { newExpression = t.assignmentExpression( From 2c7a0d57a63fd3a24cfc1e0e9d382cfb29ce8476 Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Tue, 1 Nov 2016 19:20:59 -0400 Subject: [PATCH 10/15] Fix bugs, simplify check --- .../__tests__/simplify-test.js | 16 ++++++++++++++-- .../babel-plugin-minify-simplify/src/index.js | 9 +++++---- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js index 17b1487d7..ea8bbf640 100644 --- a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js +++ b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js @@ -2211,8 +2211,11 @@ describe("simplify-plugin", () => { foo[function(){}] = foo[function(){}] + 1, foo[false] = foo[false] + 1, foo.bar.baz = foo.bar.baz + 321, - this.hello = this.hello + 1; + this.hello = this.hello + 1, + foo[null] = foo[null] + 1, + foo[undefined] = foo[undefined] + 1; `); + // TODO: foo[void 0] = foo[void 0] + 1; const expected = unpad(` foo.bar++, foo.bar += 2, @@ -2229,7 +2232,9 @@ describe("simplify-plugin", () => { foo[function () {}] = foo[function () {}] + 1, foo[false]++, foo.bar.baz += 321, - this.hello++; + this.hello++, + foo[null]++, + foo[undefined]++; `).replace(/\s+/g, ' '); expect(transform(source)).toBe(expected); @@ -2254,4 +2259,11 @@ describe("simplify-plugin", () => { expect(transform(source)).toBe(expected); }); + + it("should not simplify assignments w. template literals", () => { + + const source = unpad('foo[`x`] = foo[`x`] + 1;'); + + expect(transform(source)).toBe(source); + }); }); diff --git a/packages/babel-plugin-minify-simplify/src/index.js b/packages/babel-plugin-minify-simplify/src/index.js index c04557cf4..e5f3286b5 100644 --- a/packages/babel-plugin-minify-simplify/src/index.js +++ b/packages/babel-plugin-minify-simplify/src/index.js @@ -41,7 +41,7 @@ module.exports = ({ types: t }) => { function isEqual(arr1, arr2) { return arr1.every((value, index) => { - return value.toString() === arr2[index].toString(); + return String(value) === String(arr2[index]); }); } @@ -52,6 +52,9 @@ module.exports = ({ types: t }) => { if (node.type === 'Super') { return 'super'; } + if (node.type === 'NullLiteral') { + return 'null'; + } // augment identifiers so that they don't match // string/number literals // but still match against each other @@ -70,9 +73,7 @@ module.exports = ({ types: t }) => { const prop = path.get('property'); const propNames = [getName(prop.node)]; - while (obj.type !== 'Identifier' && - obj.type !== 'ThisExpression' && - obj.type !== 'Super') { + while (obj.type === 'MemberExpression') { const node = obj.get('property').node; if (node) { propNames.push(getName(node)); From 4f7e8ebf3c46dc41a5e855c2a9a01a2e52198342 Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Tue, 1 Nov 2016 19:27:02 -0400 Subject: [PATCH 11/15] Change postfix to prefix --- .../__tests__/simplify-test.js | 18 +++++++++--------- .../babel-plugin-minify-simplify/src/index.js | 5 +++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js index ea8bbf640..0ccc579fc 100644 --- a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js +++ b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js @@ -2154,8 +2154,8 @@ describe("simplify-plugin", () => { x = x ** 1; `); const expected = unpad(` - x++, - x--, + ++x, + --x, x *= 1, x %= 1, x <<= 1, @@ -2186,7 +2186,7 @@ describe("simplify-plugin", () => { foo *= function () {}, foo += 123, foo = 1 + foo, - x = x++, + x = ++x, foo = foo + bar + baz; `).replace(/\s+/g, ' '); @@ -2217,7 +2217,7 @@ describe("simplify-plugin", () => { `); // TODO: foo[void 0] = foo[void 0] + 1; const expected = unpad(` - foo.bar++, + ++foo.bar, foo.bar += 2, foo["x"] = foo[x] + 2, foo[x] += 2, @@ -2230,11 +2230,11 @@ describe("simplify-plugin", () => { foo[2] += 2, foo[{}] = foo[{}] + 1, foo[function () {}] = foo[function () {}] + 1, - foo[false]++, + ++foo[false], foo.bar.baz += 321, - this.hello++, - foo[null]++, - foo[undefined]++; + ++this.hello, + ++foo[null], + ++foo[undefined]; `).replace(/\s+/g, ' '); expect(transform(source)).toBe(expected); @@ -2252,7 +2252,7 @@ describe("simplify-plugin", () => { const expected = unpad(` class Foo { foo() { - super.foo++; + ++super.foo; } }; `); diff --git a/packages/babel-plugin-minify-simplify/src/index.js b/packages/babel-plugin-minify-simplify/src/index.js index e5f3286b5..ad8911832 100644 --- a/packages/babel-plugin-minify-simplify/src/index.js +++ b/packages/babel-plugin-minify-simplify/src/index.js @@ -214,11 +214,12 @@ module.exports = ({ types: t }) => { let newExpression; - // special case +=1 --> ++ + // special case x=x+1 --> ++x if (canBeUpdateExpression) { newExpression = t.updateExpression( rightExpr.node.operator + rightExpr.node.operator, - t.clone(leftExpr.node)); + t.clone(leftExpr.node), + true /* prefix */); } else { newExpression = t.assignmentExpression( From 8c0a456a0076600fb0b6c1652c90903c8dcd5304 Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Thu, 10 Nov 2016 12:06:41 -0800 Subject: [PATCH 12/15] Exclude operators for member expressions too --- .../babel-plugin-minify-simplify/__tests__/simplify-test.js | 6 ++++-- packages/babel-plugin-minify-simplify/src/index.js | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js index 0b59000b3..5b6ee5359 100644 --- a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js +++ b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js @@ -2429,7 +2429,8 @@ describe("simplify-plugin", () => { foo.bar.baz = foo.bar.baz + 321, this.hello = this.hello + 1, foo[null] = foo[null] + 1, - foo[undefined] = foo[undefined] + 1; + foo[undefined] = foo[undefined] + 1, + foo.bar = foo.bar || {}; `); // TODO: foo[void 0] = foo[void 0] + 1; const expected = unpad(` @@ -2450,7 +2451,8 @@ describe("simplify-plugin", () => { foo.bar.baz += 321, ++this.hello, ++foo[null], - ++foo[undefined]; + ++foo[undefined], + foo.bar = foo.bar || {}; `).replace(/\s+/g, ' '); expect(transform(source)).toBe(expected); diff --git a/packages/babel-plugin-minify-simplify/src/index.js b/packages/babel-plugin-minify-simplify/src/index.js index 963981615..89812a156 100644 --- a/packages/babel-plugin-minify-simplify/src/index.js +++ b/packages/babel-plugin-minify-simplify/src/index.js @@ -269,7 +269,8 @@ module.exports = ({ types: t }) => { leftPropNames.includes(undefined) || !rightPropNames || rightPropNames.includes(undefined) || - !isEqual(leftPropNames, rightPropNames)) { + !operators.has(rightExpr.node.operator) || + !isEqual(leftPropNames, rightPropNames)) { return; } } From 6eaded6f83f1b136e87afa1d60afa934a7fe80ed Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Fri, 11 Nov 2016 14:32:16 -0800 Subject: [PATCH 13/15] includes -> indexOf --- packages/babel-plugin-minify-simplify/src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/babel-plugin-minify-simplify/src/index.js b/packages/babel-plugin-minify-simplify/src/index.js index 89812a156..22f3f7192 100644 --- a/packages/babel-plugin-minify-simplify/src/index.js +++ b/packages/babel-plugin-minify-simplify/src/index.js @@ -266,9 +266,9 @@ module.exports = ({ types: t }) => { const rightPropNames = getPropNames(rightExpr.get('left')); if (!leftPropNames || - leftPropNames.includes(undefined) || + leftPropNames.indexOf(undefined) > -1 || !rightPropNames || - rightPropNames.includes(undefined) || + rightPropNames.indexOf(undefined) > -1 || !operators.has(rightExpr.node.operator) || !isEqual(leftPropNames, rightPropNames)) { return; From edd236fc61697f025161439ecae9fce14a6b4534 Mon Sep 17 00:00:00 2001 From: Boopathi Rajaa Date: Sat, 12 Nov 2016 00:10:46 +0100 Subject: [PATCH 14/15] Fix lint --- .../__tests__/simplify-test.js | 8 +-- .../babel-plugin-minify-simplify/src/index.js | 50 +++++++++---------- .../src/index.js | 6 +-- 3 files changed, 32 insertions(+), 32 deletions(-) diff --git a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js index 5b6ee5359..b57ba8ddc 100644 --- a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js +++ b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js @@ -2382,7 +2382,7 @@ describe("simplify-plugin", () => { x ^= 1, x /= 1, x **= 1; - `).replace(/\s+/g, ' '); + `).replace(/\s+/g, " "); expect(transform(source)).toBe(expected); }); @@ -2404,7 +2404,7 @@ describe("simplify-plugin", () => { foo = 1 + foo, x = ++x, foo = foo + bar + baz; - `).replace(/\s+/g, ' '); + `).replace(/\s+/g, " "); expect(transform(source)).toBe(expected); }); @@ -2453,7 +2453,7 @@ describe("simplify-plugin", () => { ++foo[null], ++foo[undefined], foo.bar = foo.bar || {}; - `).replace(/\s+/g, ' '); + `).replace(/\s+/g, " "); expect(transform(source)).toBe(expected); }); @@ -2480,7 +2480,7 @@ describe("simplify-plugin", () => { it("should not simplify assignments w. template literals", () => { - const source = unpad('foo[`x`] = foo[`x`] + 1;'); + const source = unpad("foo[`x`] = foo[`x`] + 1;"); expect(transform(source)).toBe(source); }); diff --git a/packages/babel-plugin-minify-simplify/src/index.js b/packages/babel-plugin-minify-simplify/src/index.js index 22f3f7192..8340dedb6 100644 --- a/packages/babel-plugin-minify-simplify/src/index.js +++ b/packages/babel-plugin-minify-simplify/src/index.js @@ -29,14 +29,14 @@ module.exports = ({ types: t }) => { const and = (a, b) => t.logicalExpression("&&", a, b); const operators = new Set([ - '+', '-', '*', '%', - '<<', '>>', '>>>', - '&', '|', '^', '/', - '**' + "+", "-", "*", "%", + "<<", ">>", ">>>", + "&", "|", "^", "/", + "**" ]); const updateOperators = new Set([ - '+', '-' + "+", "-" ]); function isEqual(arr1, arr2) { @@ -46,21 +46,21 @@ module.exports = ({ types: t }) => { } function getName(node) { - if (node.type === 'ThisExpression') { - return 'this'; + if (node.type === "ThisExpression") { + return "this"; } - if (node.type === 'Super') { - return 'super'; + if (node.type === "Super") { + return "super"; } - if (node.type === 'NullLiteral') { - return 'null'; + if (node.type === "NullLiteral") { + return "null"; } // augment identifiers so that they don't match // string/number literals // but still match against each other return node.name - ? node.name + '_' - : node.value /* Literal */; + ? node.name + "_" + : node.value /* Literal */; } function getPropNames(path) { @@ -68,17 +68,17 @@ module.exports = ({ types: t }) => { return; } - let obj = path.get('object'); + let obj = path.get("object"); - const prop = path.get('property'); + const prop = path.get("property"); const propNames = [getName(prop.node)]; - while (obj.type === 'MemberExpression') { - const node = obj.get('property').node; + while (obj.type === "MemberExpression") { + const node = obj.get("property").node; if (node) { propNames.push(getName(node)); } - obj = obj.get('object'); + obj = obj.get("object"); } propNames.push(getName(obj.node)); @@ -252,18 +252,18 @@ module.exports = ({ types: t }) => { AssignmentExpression(path) { - const rightExpr = path.get('right'); - const leftExpr = path.get('left'); + const rightExpr = path.get("right"); + const leftExpr = path.get("left"); const canBeUpdateExpression = ( - rightExpr.get('right').isNumericLiteral() && - rightExpr.get('right').node.value === 1 && + rightExpr.get("right").isNumericLiteral() && + rightExpr.get("right").node.value === 1 && updateOperators.has(rightExpr.node.operator)); if (leftExpr.isMemberExpression()) { const leftPropNames = getPropNames(leftExpr); - const rightPropNames = getPropNames(rightExpr.get('left')); + const rightPropNames = getPropNames(rightExpr.get("left")); if (!leftPropNames || leftPropNames.indexOf(undefined) > -1 || @@ -278,7 +278,7 @@ module.exports = ({ types: t }) => { if (!rightExpr.isBinaryExpression() || !operators.has(rightExpr.node.operator) || leftExpr.node.name !== rightExpr.node.left.name) { - return; + return; } } @@ -293,7 +293,7 @@ module.exports = ({ types: t }) => { } else { newExpression = t.assignmentExpression( - rightExpr.node.operator + '=', + rightExpr.node.operator + "=", t.clone(leftExpr.node), t.clone(rightExpr.node.right)); } diff --git a/packages/babel-plugin-transform-regexp-constructors/src/index.js b/packages/babel-plugin-transform-regexp-constructors/src/index.js index 29e62714a..9c7453bc2 100644 --- a/packages/babel-plugin-transform-regexp-constructors/src/index.js +++ b/packages/babel-plugin-transform-regexp-constructors/src/index.js @@ -23,9 +23,9 @@ module.exports = function({ types: t }) { ""; pattern = pattern - .replace(/\n/g, '\\n') - .replace(/\r/g, '\\r') - .replace(/\//g, '\\/'); + .replace(/\n/g, "\\n") + .replace(/\r/g, "\\r") + .replace(/\//g, "\\/"); path.replaceWith(t.regExpLiteral(pattern, flags)); } From b058bd0fc4783eaffb714ce080532829045b7854 Mon Sep 17 00:00:00 2001 From: Juriy Zaytsev Date: Sun, 13 Nov 2016 12:26:00 -0800 Subject: [PATCH 15/15] Improve method name --- packages/babel-plugin-minify-simplify/src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/babel-plugin-minify-simplify/src/index.js b/packages/babel-plugin-minify-simplify/src/index.js index 8340dedb6..c2f4c52c4 100644 --- a/packages/babel-plugin-minify-simplify/src/index.js +++ b/packages/babel-plugin-minify-simplify/src/index.js @@ -39,7 +39,7 @@ module.exports = ({ types: t }) => { "+", "-" ]); - function isEqual(arr1, arr2) { + function areArraysEqual(arr1, arr2) { return arr1.every((value, index) => { return String(value) === String(arr2[index]); }); @@ -270,7 +270,7 @@ module.exports = ({ types: t }) => { !rightPropNames || rightPropNames.indexOf(undefined) > -1 || !operators.has(rightExpr.node.operator) || - !isEqual(leftPropNames, rightPropNames)) { + !areArraysEqual(leftPropNames, rightPropNames)) { return; } }