From b12566c57e2b550b6c4457943da17c8c2bb64053 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Sun, 18 Jun 2017 19:33:22 -0400 Subject: [PATCH 1/4] Add test helper This simplifies tests that check that a certain code snippet gets transformed to another snippet. --- .../__tests__/minify-builtins.js | 317 +- .../__tests__/constant-folding-test.js | 473 +- .../__tests__/dead-code-elimination-test.js | 4898 ++++++++--------- .../__tests__/flip-comparisons-test.js | 170 +- .../__tests__/guarded-expressions-test.js | 182 +- .../__tests__/infinity-test.js | 133 +- .../__tests__/mangle-names-test.js | 2562 +++++---- .../__tests__/numeric-literals-test.js | 59 +- .../__tests__/replace-test.js | 280 +- .../__tests__/simplify-test.js | 4700 ++++++++-------- .../__tests__/type-constructors-test.js | 478 +- .../transform-inline-consecutive-adds-test.js | 578 +- .../__tests__/inline-env-var-test.js | 30 +- ...ansform-member-expression-literals-test.js | 90 +- .../transform-merge-sibling-variables-test.js | 298 +- .../__tests__/booleans-test.js | 25 +- .../__tests__/node-env-inline-test.js | 30 +- .../transform-property-literals-test.js | 202 +- .../transform-regexp-constructors-test.js | 204 +- .../__tests__/remove-console-test.js | 267 +- .../__tests__/remove-debugger-test.js | 78 +- ...-plugin-transform-remove-undefined-test.js | 442 +- .../__tests__/strict-equals-test.js | 124 +- .../__tests__/undefined-test.js | 39 +- .../__tests__/preset-tests.js | 251 +- utils/test-transform.js | 78 + 26 files changed, 8320 insertions(+), 8668 deletions(-) create mode 100644 utils/test-transform.js diff --git a/packages/babel-plugin-minify-builtins/__tests__/minify-builtins.js b/packages/babel-plugin-minify-builtins/__tests__/minify-builtins.js index f83413457..344396c78 100644 --- a/packages/babel-plugin-minify-builtins/__tests__/minify-builtins.js +++ b/packages/babel-plugin-minify-builtins/__tests__/minify-builtins.js @@ -1,187 +1,180 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const unpad = require("../../../utils/unpad"); -const plugin = require("../src/index"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform").snapshot( + require("../src/index") +); describe("minify-builtins", () => { - it("should minify standard built in methods", () => { - const source = unpad(` - function c() { - let a = 10; - const d = Number.isNaN(a); - Math.max(a, b) + Math.max(b, a); - return d && Number.isFinite(a); - } - `); - // Jest arranges in alphabetical order, So keeping it as _source - expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); - }); + thePlugin( + "should minify standard built in methods", + ` + function c() { + let a = 10; + const d = Number.isNaN(a); + Math.max(a, b) + Math.max(b, a); + return d && Number.isFinite(a); + } + ` + ); - it("should minify standard built in properties", () => { - const source = unpad(` - function a () { - Number.NAN + Number.NAN; - return Math.PI + Math.PI + Number.EPSILON + Number.NAN; - } - `); - expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); - }); + thePlugin( + "should minify standard built in properties", + ` + function a () { + Number.NAN + Number.NAN; + return Math.PI + Math.PI + Number.EPSILON + Number.NAN; + } + ` + ); - it("should take no of occurences in to account", () => { - const source = unpad(` - function a() { - Math.floor(a) + Math.floor(b) + Math.min(a, b); - } - `); - expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); - }); + thePlugin( + "should take no of occurences in to account", + ` + function a() { + Math.floor(a) + Math.floor(b) + Math.min(a, b); + } + ` + ); - it("should collect and minify no matter any depth", () => { - const source = unpad(` - function a (){ - Math.max(b, a); - const b = () => { - const a = Math.floor(c); - Math.min(b, a) * Math.floor(b); - function c() { - Math.floor(c) + Math.min(b, a) - } + thePlugin( + "should collect and minify no matter any depth", + ` + function a (){ + Math.max(b, a); + const b = () => { + const a = Math.floor(c); + Math.min(b, a) * Math.floor(b); + function c() { + Math.floor(c) + Math.min(b, a) } } - `); - expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); - }); + } + ` + ); - it("shouldn't minify builtins in the program scope to avoid leaking", () => { - const source = unpad(` - Math.max(c, d) - function a (){ - Math.max(b, a) + Math.max(c, d); - } - Math.max(e, f) - `); - expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); - }); + thePlugin( + "shouldn't minify builtins in the program scope to avoid leaking", + ` + Math.max(c, d) + function a (){ + Math.max(b, a) + Math.max(c, d); + } + Math.max(e, f) + ` + ); - it("should minify builtins to method scope for class declarations", () => { - const source = unpad(` - class Test { - foo() { - Math.max(c, d) + thePlugin( + "should minify builtins to method scope for class declarations", + ` + class Test { + foo() { + Math.max(c, d) + Math.max(c, d) + const c = function() { Math.max(c, d) - const c = function() { - Math.max(c, d) - Math.floor(m); - Math.floor(m); - } - } - bar() { - Math.min(c, d) - Math.min(c, d) + Math.floor(m); + Math.floor(m); } } - `); - expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); - }); + bar() { + Math.min(c, d) + Math.min(c, d) + } + } + ` + ); - it("should minify builtins to function scopes ", () => { - const source = unpad(` - var a = () => { - Math.floor(b); - Math.floor(b); - c: () => { - Math.floor(d); - Math.max(2,1); - } + thePlugin( + "should minify builtins to function scopes ", + ` + var a = () => { + Math.floor(b); + Math.floor(b); + c: () => { + Math.floor(d); + Math.max(2,1); } - A.b("asdas", function() { - Math.floor(d) + Math.max(d,e); - Math.max(e,d); - }) - A.b("asdas1", function() { - Math.floor(d) + Math.floor(d,e); - Math.max(e,d); - }) - `); - expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); - }); + } + A.b("asdas", function() { + Math.floor(d) + Math.max(d,e); + Math.max(e,d); + }) + A.b("asdas1", function() { + Math.floor(d) + Math.floor(d,e); + Math.max(e,d); + }) + ` + ); - it("should collect and minify in segments in any depth if there is no LCA", () => { - const source = unpad(` - function b(){ + thePlugin( + "should collect and minify in segments in any depth if there is no LCA", + ` + function b(){ + Math.floor(as, bb); + function d(){ Math.floor(as, bb); - function d(){ - Math.floor(as, bb); - } } - const a = { - c : () => Math.floor(bbb) + Math.floor(bbb) , - d : () => { - Math.abs(aa); - Math.abs(aa); + } + const a = { + c : () => Math.floor(bbb) + Math.floor(bbb) , + d : () => { + Math.abs(aa); + Math.abs(aa); + Math.floor(aa); + return () => { Math.floor(aa); - return () => { - Math.floor(aa); - } - }, - e : () => Math.abs(aa) + Math.abs(aa) - }; - class A { - constructor() { - let a = Math.floor(b,c) + Math.floor(b,c); - } - c() { - Math.floor(asdas); - Math.floor(dasda); - } - d() { - var a = Math.floor; - a(aa, bb); - Math.floor(aa, bb); - } - }; - new A() - `); - expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); - }); + } + }, + e : () => Math.abs(aa) + Math.abs(aa) + }; + class A { + constructor() { + let a = Math.floor(b,c) + Math.floor(b,c); + } + c() { + Math.floor(asdas); + Math.floor(dasda); + } + d() { + var a = Math.floor; + a(aa, bb); + Math.floor(aa, bb); + } + }; + new A() + ` + ); - it("should evalaute expressions if applicable and optimize it", () => { - const source = unpad(` - const a = Math.max(Math.floor(2), 5); - let b = 1.8; - let x = Math.floor(Math.max(a, b)); - foo(x); - `); - expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); - }); + thePlugin( + "should evalaute expressions if applicable and optimize it", + ` + const a = Math.max(Math.floor(2), 5); + let b = 1.8; + let x = Math.floor(Math.max(a, b)); + foo(x); + ` + ); - it("should not evaluate if its side effecty", () => { - const source = unpad(` - Math.max(foo(), 1); - Math.random(); - `); - expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); - }); + thePlugin( + "should not evaluate if its side effecty", + ` + Math.max(foo(), 1); + Math.random(); + ` + ); - it("should not minify for computed properties", () => { - const source = unpad(` - let max = "floor"; - Math[max](1.5); - `); - expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); - }); + thePlugin( + "should not minify for computed properties", + ` + let max = "floor"; + Math[max](1.5); + ` + ); - it("should not minify for arrow fn without block statment", () => { - const source = unpad(` - const a = () => Math.floor(b) + Math.floor(b); - `); - expect({ _source: source, expected: transform(source) }).toMatchSnapshot(); - }); + thePlugin( + "should not minify for arrow fn without block statment", + ` + const a = () => Math.floor(b) + Math.floor(b); + ` + ); }); diff --git a/packages/babel-plugin-minify-constant-folding/__tests__/constant-folding-test.js b/packages/babel-plugin-minify-constant-folding/__tests__/constant-folding-test.js index 352027fa6..b831791e2 100644 --- a/packages/babel-plugin-minify-constant-folding/__tests__/constant-folding-test.js +++ b/packages/babel-plugin-minify-constant-folding/__tests__/constant-folding-test.js @@ -1,254 +1,229 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const unpad = require("../../../utils/unpad"); - -function transform(code) { - return babel.transform(code, { - plugins: [require("../src/index")] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("constant-folding-plugin", () => { - it("should evaluate some expressions", () => { - const source = unpad(` - "a" + "b" - 2 * 3; - 1/3; - 4 | 3; - a(), b(); - var x = 1; - foo(x); - "b" + a + "c" + "d" + g + z + "f" + "h" + "z" - `); - - const expected = unpad(` - "ab"; - 6; - 1 / 3; - 7; - a(), b(); - var x = 1; - foo(x); - "b" + a + "cd" + g + z + "fhz"; - `); - expect(transform(source)).toBe(expected); - }); - - it("should skip -0", () => { - const source = unpad(` - -0; - +-0; - +0; - `); - - const expected = unpad(` - -0; - -0; - 0; - `); - expect(transform(source)).toBe(expected); - }); - - it("should handle runtime errors", () => { - const source = unpad(` - try { - x({ - toString: 0 - } + ''); - } catch (e) {} - `); - expect(transform(source)).toBe(source); - }); - - xit("should handle script escape", () => { - const source = unpad(` - " { - const source = unpad(` - " { - const source = unpad(` - " { - const source = unpad(` - var x = "'cool'" + "test"; - `); - const expected = unpad(` - var x = "'cool'test"; - `); - expect(transform(source)).toBe(expected); - }); - - it("should handle Array methods on array literals", () => { - const source = unpad( - ` - [1, 2, 3].push([4, 5, 6]); - [1, 2, 3]["push"]([4, 5, 6]); - - [1, 2, 3].join(); - ["a", "b", "c"].join(); - ["a", "b", "c"].join("@"); - - [1, 2, 3].length; - [1, 2, 3][1]; - [1, 2, 3]["1"]; - [1, 2, 3][4]; - - [].shift(); - [1, 2, 3].shift(); - - [1, 2, 3].slice(); - [1, 2, 3].slice(1); - [1, 2, 3].slice(0, 2); - [1, 2, 3].slice(0, -1); - - [1, 2, 3].pop(); - [a, b, c].pop(); - [].pop(); - - [a, b, c].reverse(); - [1, 2, 3].reverse(); - - [1, 2, 3].splice(1); - [1, 2, 3, 4].splice(1, 2); - ` - ); - const expected = unpad( - ` - 4; - 4; - - "1,2,3"; - "a,b,c"; - "a@b@c"; - - 3; - 2; - 2; - void 0; - - void 0; - 2; - - [1, 2, 3]; - [2, 3]; - [1, 2]; - [1, 2, 3].slice(0, -1); - - 3; - c; - void 0; - - [c, b, a]; - [3, 2, 1]; - - [2, 3]; - [2, 3]; - ` - ); - expect(transform(source)).toBe(expected); - }); - it("should ignore bad calls to array expression methods", () => { - const source = unpad( - ` - [1, 2, 3][concat]([4, 5, 6]); - [a, "b", "c"].join(); - ["a", "b", "c"].join(a); - [1, 2, 3].splice("a"); - ` - ); - expect(transform(source)).toBe(source); - }); - it("should ignore bad calls to string expression methods", () => { - const source = unpad( - ` - "abc".something; - "abc"["something"]; - ` - ); - expect(transform(source)).toBe(source); - }); - it("should handle String methods on string literals", () => { - const source = unpad( - ` - "a,b,c".split(","); - "a,b,c".split(""); - "a,b,c".split(); - "abc"[0]; - "abc"["0"]; - "abc"[4]; - "abc".charAt(); - "abc".charAt(1); - "abc".charCodeAt(); - "abc".charCodeAt(1); - "abc".length; - - "\u{1f44d}".charCodeAt(); - "\u{1f44d}".charCodeAt(1); - "\u{1f44d}".codePointAt(); - "\u{1f44d}".codePointAt(1); - ` - ); - - const expected = unpad( - ` - ["a", "b", "c"]; - ["a", ",", "b", ",", "c"]; - ["a,b,c"]; - "a"; - "a"; - void 0; - "a"; - "b"; - 97; - 98; - 3; - - ${0xd83d}; - ${0xdc4d}; - ${0x1f44d}; - ${0xdc4d}; - ` - ); - expect(transform(source)).toBe(expected); - }); - - it("shouldn’t crash on toString() calls or accesses", () => { - const source = unpad( - ` - "foo".toString(); - ["foo", "bar"].toString(); - ({}).toString(); - "foo".toString; - ["foo", "bar"].toString; - ({}).toString; - ` - ); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should evaluate some expressions", + ` + "a" + "b" + 2 * 3; + 1/3; + 4 | 3; + a(), b(); + var x = 1; + foo(x); + "b" + a + "c" + "d" + g + z + "f" + "h" + "z" + `, + ` + "ab"; + 6; + 1 / 3; + 7; + a(), b(); + var x = 1; + foo(x); + "b" + a + "cd" + g + z + "fhz"; + ` + ); + + thePlugin( + "should skip -0", + ` + -0; + +-0; + +0; + `, + ` + -0; + -0; + 0; + ` + ); + + thePlugin( + "should handle runtime errors", + ` + try { + x({ + toString: 0 + } + ''); + } catch (e) {} + ` + ); + + thePlugin.skip( + "should handle script escape", + ` + " { - it("should remove bindings with no references", () => { - const source = "function foo() {var x = 1;}"; - const expected = "function foo() {}"; - expect(transform(source)).toBe(expected); - }); - - it("should keep bindings in the global namespace ", () => { - const source = "var x = 1;"; - const expected = "var x = 1;"; - expect(transform(source)).toBe(expected); - }); - - it("should handle impure right-hands", () => { - const source = "function foo() { var x = f(); }"; - const expected = unpad(` - function foo() { - f(); + thePlugin( + "should remove bindings with no references", + ` + function foo() {var x = 1;} + `, + ` + function foo() {} + ` + ); + + thePlugin( + "should keep bindings in the global namespace", + ` + var x = 1; + `, + ` + var x = 1; + ` + ); + + thePlugin( + "should handle impure right-hands", + ` + function foo() { var x = f(); } + `, + ` + function foo() { + f(); + } + ` + ); + + thePlugin( + "should remove unused params", + ` + _(function bar(p) { + return 1; + }); + function foo(w) { + return 1; + } + foo(); + foo(); + var bar = function (a) { + return a; + }; + bar(); + bar(); + + class A { + foo(p) { + } + } + new A(); + `, + ` + _(function () { + return 1; + }); + function foo() { + return 1; + } + foo(); + foo(); + var bar = function (a) { + return a; + }; + bar(); + bar(); + + class A { + foo() {} + } + new A(); + ` + ); + + thePlugin( + "should NOT remove params when keepFnArgs is true (preserve fn.length)", + ` + function foo(p) { + return 1; + } + function bar(q) { + return q + 1; + } + class A { + foo(p) { + return p; + } + bar(q) { + return 1; } - `); - expect(transform(source)).toBe(expected); - }); + } + foo(); + bar(); + new A(); + `, + { + plugins: [[deadcode, { keepFnArgs: true }]] + } + ); + + thePlugin( + "should handle all cases of parameter list - and remove unused ones", + ` + function a(foo, bar, baz) { + return foo; + } + function b(foo, bar, baz) { + return baz; + } + function c(foo, {bar}, baz) { + return bar; + } + function d({foo}, {bar}, baz) { + return foo; + } + function e({foo}, bar = sideEffect(), baz) { + return foo; + } + function e({foo}, bar = {}, baz) { + return foo; + } + `, + ` + function a(foo) { + return foo; + } + function b(foo, bar, baz) { + return baz; + } + function c(foo, { bar }) { + return bar; + } + function d({ foo }, { bar }) { + return foo; + } + function e({ foo }, bar = sideEffect()) { + return foo; + } + function e({ foo }, bar = {}) { + return foo; + } + ` + ); + + thePlugin( + "should inline binding with one reference", + ` + function foo() { + var x = 1; + console.log(x); + } + `, + ` + function foo() { + console.log(1); + } + ` + ); - it("should remove unused params", () => { - const source = unpad(` - _(function bar(p) { - return 1; + // This isn't considered pure. (it should) + thePlugin( + "should inline binding with one reference 2", + ` + function foo() { + var y = 1, x = { y: y }; + foo.exports = x; + } + `, + ` + function foo() { + foo.exports = { y: 1 }; + } + ` + ); + + thePlugin( + "should not inline objects literals in loops", + ` + function foo() { + var x = { y: 1 }; + while (true) foo(x); + var y = { y: 1 }; + for (;;) foo(y); + var z = ['foo']; + while (true) foo(z); + var bar = function () {}; + while (true) foo(bar); + } + ` + ); + + thePlugin( + "should not inline object literals in exprs in loops", + ` + function a(p) { + var w = p || []; + f(function (foo) { + return w.concat(foo); }); - function foo(w) { - return 1; + } + ` + ); + + thePlugin( + "should inline objects in if statements", + ` + function foo() { + var x = { y: 1 }, y = ['foo'], z = function () {}; + if (wat) foo(x, y, z); + } + `, + ` + function foo() { + if (wat) foo({ y: 1 }, ['foo'], function () {}); + } + ` + ); + + thePlugin( + "should not inline objects in functions", + ` + function foo() { + var x = { y: 1 }, + y = ['foo'], + z = function () {}; + f(function () { + foo(x, y, z); + }); + } + ` + ); + + thePlugin( + "should remove side effectless statements", + ` + function foo() { + 1; + } + `, + ` + function foo() {} + ` + ); + + thePlugin( + "should work with multiple scopes", + ` + function x() { + var i = 1; + function y() { + console.log(i); + } + y(); + y(); + } + `, + ` + function x() { + function y() { + console.log(1); } - foo(); - foo(); - var bar = function (a) { - return a; - }; - bar(); - bar(); + y(); + y(); + } + ` + ); - class A { - foo(p) { - } + thePlugin("should inline function decl", ` + function foo() { + function x() { + return 1; } - new A(); - `); - - const expected = unpad(` - _(function () { + x(); + } + `, + ` + function foo() { + (function () { return 1; - }); - function foo() { + })(); + } + ` + ); + + thePlugin( + "should inline function expressions", + ` + function foo() { + var x = function() { return 1; - } - foo(); - foo(); - var bar = function (a) { + }; + x(); + } + `, + ` + function foo() { + (function () { + return 1; + })(); + } + ` + ); + + thePlugin( + "should not inline in a different scope", + ` + function foo() { + var x = function (a) { return a; }; - bar(); - bar(); - - class A { - foo() {} - } - new A(); - `); - expect(transform(source)).toBe(expected); - }); + while (1) x(1); + } + ` + ); + + thePlugin( + "should handle recursion", + ` + function baz() { + var bar = function foo(config) { + return foo; + }; + exports.foo = bar; + } + `, + ` + function baz() { + exports.foo = function foo() { + return foo; + }; + } + ` + ); + + thePlugin( + "should handle recursion 2", + ` + function baz() { + var foo = function foo(config) { + return foo; + }; + exports.foo = foo; + } + `, + ` + function baz() { + exports.foo = function foo() { + return foo; + }; + } + ` + ); - it("should NOT remove params when keepFnArgs is true (preserve fn.length)", () => { - const source = unpad(` - function foo(p) { - return 1; - } - function bar(q) { - return q + 1; + thePlugin( + "should handle mutual recursion", + ` + function baz() { + function foo() { + return bar(); } - class A { - foo(p) { - return p; - } - bar(q) { - return 1; + function bar() { + return foo(); + } + } + ` + ); + + thePlugin( + "should not inline vars with multiple references", + ` + function foo() { + var x = function() { + if (!y) { + y = 1; + } + }; + x(); + x(); + var y = null; + } + `, + ` + function foo() { + var x = function () { + if (!y) { + y = 1; } + }; + x(); + x(); + var y = null; + } + ` + ); + + thePlugin( + "should remove redundant returns", + ` + function foo() { + if (a) { + y(); + return; } - foo(); - bar(); - new A(); - `); - - const expected = source; - - expect(transform(source, { keepFnArgs: true })).toBe(expected); - }); - - it("should handle all cases of parameter list - and remove unused ones", () => { - const source = unpad(` - function a(foo, bar, baz) { - return foo; - } - function b(foo, bar, baz) { - return baz; + } + `, + ` + function foo() { + if (a) { + y(); } - function c(foo, {bar}, baz) { - return bar; + } + ` + ); + + thePlugin( + "should remove redundant returns part 2", + ` + function foo() { + y(); + return; + } + `, + ` + function foo() { + y(); + } + ` + ); + + thePlugin( + "should remove redundant returns (complex)", + ` + function foo() { + if (a) { + y(); + if (b) { + return; + } + return; } - function d({foo}, {bar}, baz) { - return foo; + return; + } + `, + ` + function foo() { + if (a) { + y(); + if (b) {} } - function e({foo}, bar = sideEffect(), baz) { - return foo; + } + ` + ); + + thePlugin( + "should keep needed returns", + ` + function foo() { + if (a) { + y(); + return; } - function e({foo}, bar = {}, baz) { - return foo; + x(); + } + `, + ` + function foo() { + if (a) { + y(); + return; } - `); - const expected = unpad(` - function a(foo) { - return foo; + x(); + } + ` + ); + + thePlugin( + "should remove code unreachable after return", + ` + function foo() { + z(); + return; + x(); + } + `, + ` + function foo() { + z(); + } + ` + ); + + thePlugin( + "should be fine with fun decl after return", + ` + function foo() { + z(); + z(); + return 22; + function z() { + wow(); } - function b(foo, bar, baz) { - return baz; + } + `, + ` + function foo() { + z(); + z(); + return 22; + function z() { + wow(); } - function c(foo, { bar }) { - return bar; + } + ` + ); + + thePlugin( + "should handle returns that were orphaned", + ` + var a = true; + function foo() { + if (a) return; + x(); + } + `, + ` + var a = true; + function foo() {} + ` + ); + + thePlugin( + "should handle returns that were orphaned 2", + ` + var a = true; + function foo() { + if (a) return 1; + x(); + } + `, + ` + var a = true; + function foo() { + return 1; + } + ` + ); + + thePlugin( + "should handle orphaned + redundant returns", + ` + var x = true; + function foo() { + if (b) { + if (x) { + z(); + return; + } + y(); } - function d({ foo }, { bar }) { - return foo; + } + `, + ` + var x = true; + function foo() { + if (b) { + z(); } - function e({ foo }, bar = sideEffect()) { - return foo; + } + ` + ); + + thePlugin( + "should remove functions only called in themselves", + ` + function foo() { + function baz() { + function bar() { + baz(); + } + bar(); + bar(); } - function e({ foo }, bar = {}) { - return foo; + } + `, + ` + function foo() {} + ` + ); + + thePlugin( + "should remove functions only called in themselves 2", + ` + function foo() { + var baz = function () { + function bar() { + baz(); + } + bar(); + bar(); + }; + } + `, + ` + function foo() {} + ` + ); + + thePlugin( + "should remove functions only called in themselves 3", + ` + function foo() { + function boo() {} + function baz() { + function bar() { + baz(); + } + bar(); + bar(); + boo(); + } + } + `, + ` + function foo() {} + ` + ); + + thePlugin( + "should remove functions only called in themselves 3", + ` + (function () { + function foo () { + console.log( 'this function was included!' ); } - `); - expect(transform(source)).toBe(expected); - }); - it("should inline binding with one reference", () => { - const source = unpad(` - function foo() { - var x = 1; - console.log(x); + function bar () { + console.log( 'this function was not' ); + baz(); } - `); - const expected = unpad(` - function foo() { - console.log(1); + + function baz () { + console.log( 'neither was this' ); } - `); - expect(transform(source).trim()).toBe(expected); - }); + foo(); + })(); + `, + ` + (function () { - // This isn't considered pure. (it should) - it("should inline binding with one reference 2", () => { - const source = unpad(` - function foo() { - var y = 1, x = { y: y }; - foo.exports = x; - } - `); - const expected = unpad(` - function foo() { - foo.exports = { y: 1 }; - } - `); + (function () { + console.log('this function was included!'); + })(); + })(); + ` + ); - expect(transform(source).trim()).toBe(expected); - }); + thePlugin( + "should remove dead if statements", + ` + if (1) { + foo(); + } + if (false) { + foo(); + } else { + bar(); + } + `, + ` + foo(); + + bar(); + ` + ); + + thePlugin( + "should remove empty if statements block", + ` + if (a) { + } else { + foo(); + } + if (a) { + foo(); + } else { - it("should not inline objects literals in loops", () => { - const source = unpad(` - function foo() { - var x = { y: 1 }; - while (true) foo(x); - var y = { y: 1 }; - for (;;) foo(y); - var z = ['foo']; - while (true) foo(z); - var bar = function () {}; - while (true) foo(bar); - } - `); - const expected = unpad(` - function foo() { - var x = { y: 1 }; - while (true) foo(x); - var y = { y: 1 }; - for (;;) foo(y); - var z = ['foo']; - while (true) foo(z); - var bar = function () {}; - while (true) foo(bar); + } + `, + ` + if (!a) { + foo(); + } + if (a) { + foo(); + } + ` + ); + + thePlugin( + "should evaluate conditional expressions", + ` + true ? a() : b(); + `, + ` + a(); + ` + ); + + thePlugin( + "should evaluate conditional expressions 2", + ` + false ? a() : b(); + `, + ` + b(); + ` + ); + + thePlugin( + "should evaluate conditional expressions 3", + ` + 'foo' ? a() : b(); + `, + ` + a(); + ` + ); + + thePlugin( + "should evaluate conditional expressions 4", + ` + null ? a() : b(); + `, + ` + b(); + ` + ); + + thePlugin( + "should evaluate conditional expressions 5", + ` + 'foo' === 'foo' ? a() : b(); + `, + ` + a(); + ` + ); + + thePlugin( + "should evaluate conditional expressions 6", + ` + 'foo' !== 'bar' ? a() : b(); + `, + ` + a(); + ` + ); + + thePlugin( + "should not remove needed expressions", + ` + var n = 1; + if (foo) n; + console.log(n); + `, + ` + var n = 1; + if (foo) ; + console.log(n); + ` + ); + + thePlugin( + "should not remove needed expressions", + ` + function foo(a) { + var a = a ? a : a; + } + `, + ` + function foo(a) { + var a = a ? a : a; + } + ` + ); + + thePlugin( + "should join the assignment and def", + ` + var x; + x = 1; + `, + ` + var x = 1; + ` + ); + + thePlugin( + "should not replace the wrong things", + ` + function foo() { + var n = 1; + wow(n); + function wat() { + var n = 2; + wow(n); } - `); + return wat; + } + `, + ` + function foo() { + wow(1); - expect(transform(source).trim()).toBe(expected); - }); - - it("should not inline object literals in exprs in loops", () => { - const source = unpad(` - function a(p) { - var w = p || []; - f(function (foo) { - return w.concat(foo); - }); + return function () { + wow(2); + }; + } + ` + ); + + thePlugin( + "should handle case blocks ", + ` + function a() { + switch (foo) { + case 6: + return bar; + break; } - `); + } + `, + ` + function a() { + switch (foo) { + case 6: + return bar; + break; + } + } + ` + ); - const expected = unpad(` - function a(p) { - var w = p || []; - f(function (foo) { - return w.concat(foo); - }); + // TODO: Handle this (blocks that have no semantic meaning). + thePlugin.skip( + "should understand extraneous blocks", + ` + function a() { + var f = 25; + function b() { + { + var f = "wow"; + } + function c() { + f.bar(); + } + c(); + c(); + } + function d() { + bar(f); + } + d(); + d(); + b(); + b(); + } + `, + ` + function a() { + function b() { + {} + function c() { + "wow".bar(); + } + c(); + c(); + } + function d() { + bar(25); + } + d(); + d(); + b(); + b(); + } + ` + ); + + thePlugin( + "should understand closures", + ` + function a() { + var f = 25; + function b() { + var f = "wow"; + function c() { + f.bar(); + } + c(); + c(); + } + function d() { + bar(f); + } + d(); + d(); + b(); + b(); + } + `, + ` + function a() { + function b() { + function c() { + "wow".bar(); + } + c(); + c(); + } + function d() { + bar(25); + } + d(); + d(); + b(); + b(); + } + ` + ); + + thePlugin( + "should handle vars in if statements", + ` + function a() { + if (x()) { + var foo = 1; + } + bar(foo); + } + `, + ` + function a() { + if (x()) { + var foo = 1; + } + bar(foo); + } + ` + ); + + thePlugin( + "should handle vars in if statements 2", + ` + function a() { + if (x()) var foo = 1; + bar(foo); + } + `, + ` + function a() { + if (x()) var foo = 1; + bar(foo); + } + ` + ); + + thePlugin( + "should handle vars in for statements", + ` + function a() { + for (;;) var foo = 1; + bar(foo); + } + `, + ` + function a() { + for (;;) var foo = 1; + bar(foo); + } + ` + ); + + thePlugin( + "should handle for statements 2", + ` + function a() { + for (;;) { + var foo = 1; + bar(foo); } - `); + } + `, + ` + function a() { + for (;;) { + bar(1); + } + } + ` + ); + + thePlugin( + "should remove binding and assignment", + ` + function a() { + var a, b, c; + a = 1; + b = 2; + } + `, + ` + function a() {} + ` + ); + + thePlugin( + "should nore remove binding and assignment if the value is used", + ` + function a() { + var x = 1; + while (a) wow = x += 1; + } + `, + ` + function a() { + var x = 1; + while (a) wow = x += 1; + } + ` + ); + + thePlugin( + "should keep side-effectful assignment values", + ` + function a() { + var x; + x = wow(); + } + `, + ` + function a() { + wow(); + } + ` + ); + + thePlugin( + "should not evaluate this binary expression to truthy", + ` + function boo() { + var bar = foo || []; + if (!bar || baz.length === 0) { + return 'wow'; + } + } + `, + ` + function boo() { + var bar = foo || []; + if (!bar || baz.length === 0) { + return 'wow'; + } + } + ` + ); + + thePlugin( + "eval the following to false", + ` + function bar () { + var x = foo || 'boo'; + bar = x === 'wow' ? ' ' + z : ''; + } + `, + ` + function bar() { + var x = foo || 'boo'; + bar = x === 'wow' ? ' ' + z : ''; + } + ` + ); + + thePlugin( + "should get rid of the constant violations", + ` + function bar () { + var x = foo(); + x = bar(); + } + `, + ` + function bar() { + foo(); - expect(transform(source).trim()).toBe(expected); - }); + bar(); + } + ` + ); + + thePlugin( + "should remove names from NFE", + ` + function bar() { + return function wow() { + return boo(); + }; + } + `, + ` + function bar() { + return function () { + return boo(); + }; + } + ` + ); + + thePlugin( + "should not remove names from NFE when referenced", + ` + function bar() { + return function wow() { + return wow(); + }; + } + `, + ` + function bar() { + return function wow() { + return wow(); + }; + } + ` + ); + + thePlugin( + "should remove name from NFE when shadowed", + ` + function bar() { + return function wow() { + var wow = foo; + wow(); + return wow; + }; + } + `, + ` + function bar() { + return function () { + var wow = foo; + wow(); + return wow; + }; + } + ` + ); - it("should inline objects in if statements", () => { - const source = unpad(` - function foo() { - var x = { y: 1 }, y = ['foo'], z = function () {}; - if (wat) foo(x, y, z); - } - `); - const expected = unpad(` - function foo() { - if (wat) foo({ y: 1 }, ['foo'], function () {}); - } - `); + // issue#81 + thePlugin( + "should NOT remove name from NFE when referenced - issue#81", + ` + (function (require, module, exports) { + var Hub = function Hub(file, options) { + (0, _classCallCheck3.default)(this, Hub); + }; + module.exports = Hub; + })(require, module, exports); + `, + ` + (function (require, module) { + module.exports = function Hub() { + (0, _classCallCheck3.default)(this, Hub); + }; + })(require, module, exports); + ` + ); - expect(transform(source).trim()).toBe(expected); - }); + thePlugin( + "should remove name from NFE when replaced - issue#81", + ` + (function () { + var x = function foo() {}; + module.exports = x; + })(); + `, + ` + (function () { + module.exports = function () {}; + })(); + ` + ); - it("should not inline objects in functions", () => { - const source = unpad(` - function foo() { - var x = { y: 1 }, - y = ['foo'], - z = function () {}; - f(function () { - foo(x, y , z); - }); - } - `); - const expected = unpad(` - function foo() { - var x = { y: 1 }, - y = ['foo'], - z = function () {}; - f(function () { - foo(x, y, z); - }); - } - `); + thePlugin( + "should preserve fn names when keepFnName is true", + ` + (function () { + function A() {} + exports.A = A; + var B = function B() {}; + exports.B = B; + onClick(function C() {}); + })(); + `, + ` + (function () { + exports.A = function A() {}; - expect(transform(source).trim()).toBe(expected); - }); + exports.B = function B() {}; + onClick(function C() {}); + })(); + `, + { + plugins: [[deadcode, { keepFnName: true }]] + } + ); + + thePlugin( + "should preserve class names when keepClassName is true", + ` + (function () { + class A {} + exports.A = A; + var B = class B {}; + exports.B = B; + class AA {} new AA() + })(); + `, + ` + (function () { + exports.A = class A {}; - it("should remove side effectless statements", () => { - const source = unpad(` - function foo() { - 1; - } - `); - const expected = unpad(` - function foo() {} - `); + exports.B = class B {}; + new class AA {}(); + })(); + `, + { + plugins: [[deadcode, { keepClassName: true }]] + } + ); - expect(transform(source).trim()).toBe(expected); - }); + // NCE = Named Class Expressions + thePlugin( + "should remove name from NCE", + ` + var Foo = class Bar {}; + `, + ` + var Foo = class {}; + ` + ); + + thePlugin( + "should not remove referenced name from NCE", + ` + var Foo = class Bar { + constructor() { + console.log(Bar); + } + }; + ` + ); - it("should work with multiple scopes", () => { - const source = unpad(` - function x() { - var i = 1; - function y() { - console.log(i); - } - y(); - y(); - } - `); - const expected = unpad(` - function x() { - function y() { - console.log(1); - } - y(); - y(); - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should inline function decl", () => { - const source = unpad(` - function foo() { - function x() { - return 1; - } - x(); - } - `); - const expected = unpad(` - function foo() { - (function () { - return 1; - })(); - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should inline function expressions", () => { - const source = unpad(` - function foo() { - var x = function() { - return 1; - }; - x(); - } - `); - const expected = unpad(` - function foo() { - (function () { - return 1; - })(); - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should not inline in a different scope", () => { - const source = unpad(` - function foo() { - var x = function (a) { - return a; - }; - while (1) x(1); - } - `); - const expected = unpad(` - function foo() { - var x = function (a) { - return a; - }; - while (1) x(1); - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should handle recursion", () => { - const source = unpad(` - function baz() { - var bar = function foo(config) { - return foo; - }; - exports.foo = bar; - } - `); - const expected = unpad(` - function baz() { - exports.foo = function foo() { - return foo; - }; - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should handle recursion 2", () => { - const source = unpad(` - function baz() { - var foo = function foo(config) { - return foo; - }; - exports.foo = foo; - } - `); - const expected = unpad(` - function baz() { - exports.foo = function foo() { - return foo; - }; - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should handle mutual recursion", () => { - const source = unpad(` - function baz() { - function foo() { - return bar(); - } - function bar() { - return foo(); - } - } - `); - const expected = unpad(` - function baz() { - function foo() { - return bar(); - } - function bar() { - return foo(); - } - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should not inline vars with multiple references", () => { - const source = unpad(` - function foo() { - var x = function() { - if (!y) { - y = 1; - } - }; - x(); - x(); - var y = null; - } - `); - - const expected = unpad(` - function foo() { - var x = function () { - if (!y) { - y = 1; - } - }; - x(); - x(); - var y = null; - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should remove redundant returns", () => { - const source = unpad(` - function foo() { - if (a) { - y(); - return; - } - } - `); - const expected = unpad(` - function foo() { - if (a) { - y(); - } - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should remove redundant returns part 2", () => { - const source = unpad(` - function foo() { - y(); - return; - } - `); - const expected = unpad(` - function foo() { - y(); - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should remove redundant returns (complex)", () => { - const source = unpad(` - function foo() { - if (a) { - y(); - if (b) { - return; - } - return; - } - return; - } - `); - const expected = unpad(` - function foo() { - if (a) { - y(); - if (b) {} - } - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should keep needed returns", () => { - const source = unpad(` - function foo() { - if (a) { - y(); - return; - } - x(); - } - `); - const expected = unpad(` - function foo() { - if (a) { - y(); - return; - } - x(); - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should remove code unreachable after return", () => { - const source = unpad(` - function foo() { - z(); - return; - x(); - } - `); - const expected = unpad(` - function foo() { - z(); - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should be fine with fun decl after return", () => { - const source = unpad(` - function foo() { - z(); - z(); - return 22; - function z() { - wow(); - } - } - `); - const expected = unpad(` - function foo() { - z(); - z(); - return 22; - function z() { - wow(); - } - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should handle returns that were orphaned", () => { - const source = unpad(` - var a = true; - function foo() { - if (a) return; - x(); - } - `); - const expected = unpad(` - var a = true; - function foo() {} - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should handle returns that were orphaned 2", () => { - const source = unpad(` - var a = true; - function foo() { - if (a) return 1; - x(); - } - `); - const expected = unpad(` - var a = true; - function foo() { - return 1; - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should handle orphaned + redundant returns", () => { - const source = unpad(` - var x = true; - function foo() { - if (b) { - if (x) { - z(); - return; - } - y(); - } - } - `); - const expected = unpad(` - var x = true; - function foo() { - if (b) { - z(); - } - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should remove functions only called in themselves", () => { - const source = unpad(` - function foo() { - function baz() { - function bar() { - baz(); - } - bar(); - bar(); - } - } - `); - const expected = "function foo() {}"; - - expect(transform(source).trim()).toBe(expected); - }); - - it("should remove functions only called in themselves 2", () => { - const source = unpad(` - function foo() { - var baz = function () { - function bar() { - baz(); - } - bar(); - bar(); - }; - } - `); - const expected = "function foo() {}"; - - expect(transform(source).trim()).toBe(expected); - }); - - it("should remove functions only called in themselves 3", () => { - const source = unpad(` - function foo() { - function boo() {} - function baz() { - function bar() { - baz(); - } - bar(); - bar(); - boo(); - } - } - `); - const expected = "function foo() {}"; - - expect(transform(source).trim()).toBe(expected); - }); - - it("should remove functions only called in themselves 3", () => { - const source = unpad(` - (function () { - function foo () { - console.log( 'this function was included!' ); - } - - function bar () { - console.log( 'this function was not' ); - baz(); - } - - function baz () { - console.log( 'neither was this' ); - } - - foo(); - })(); - `); - const expected = unpad(` - (function () { - - (function () { - console.log('this function was included!'); - })(); - })(); - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should remove dead if statements", () => { - const source = unpad(` - if (1) { - foo(); - } - if (false) { - foo(); - } else { - bar(); - } - `); - const expected = unpad(` - foo(); - - bar(); - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should remove empty if statements block", () => { - const source = unpad(` - if (a) { - } else { - foo(); - } - if (a) { - foo(); - } else { - - } - `); - const expected = unpad(` - if (!a) { - foo(); - } - if (a) { - foo(); - } - `); - expect(transform(source).trim()).toBe(expected); - }); - - it("should evaluate conditional expressions", () => { - const source = "true ? a() : b();"; - const expected = "a();"; - expect(transform(source).trim()).toBe(expected); - }); - - it("should evaluate conditional expressions 2", () => { - const source = "false ? a() : b();"; - const expected = "b();"; - expect(transform(source).trim()).toBe(expected); - }); - - it("should evaluate conditional expressions 3", () => { - const source = "'foo' ? a() : b();"; - const expected = "a();"; - expect(transform(source).trim()).toBe(expected); - }); - - it("should evaluate conditional expressions 4", () => { - const source = "null ? a() : b();"; - const expected = "b();"; - expect(transform(source).trim()).toBe(expected); - }); - - it("should evaluate conditional expressions 5", () => { - const source = "'foo' === 'foo' ? a() : b();"; - const expected = "a();"; - expect(transform(source).trim()).toBe(expected); - }); - - it("should evaluate conditional expressions 6", () => { - const source = "'foo' !== 'bar' ? a() : b();"; - const expected = "a();"; - expect(transform(source).trim()).toBe(expected); - }); - - it("should not remove needed expressions", () => { - const source = unpad(` - var n = 1; - if (foo) n; - console.log(n); - `); - const expected = unpad(` - var n = 1; - if (foo) ; - console.log(n); - `); - expect(transform(source).trim()).toBe(expected); - }); - - it("should not remove needed expressions", () => { - const source = unpad(` - function foo(a) { - var a = a ? a : a; - } - `); - const expected = unpad(` - function foo(a) { - var a = a ? a : a; - } - `); - expect(transform(source).trim()).toBe(expected); - }); - - it("should join the assignment and def", () => { - const source = unpad(` - var x; - x = 1; - `); - - const expected = unpad(` - var x = 1; - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not replace the wrong things", () => { - const source = unpad(` - function foo() { - var n = 1; - wow(n); - function wat() { - var n = 2; - wow(n); - } - return wat; - } - `); - - const expected = unpad(` - function foo() { - wow(1); - - return function () { - wow(2); - }; - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should handle case blocks ", () => { - const source = unpad(` - function a() { - switch (foo) { - case 6: - return bar; - break; - } - } - `); - - const expected = unpad(` - function a() { - switch (foo) { - case 6: - return bar; - break; - } - } - `); - expect(transform(source)).toBe(expected); - }); - - // TODO: Handle this (blocks that have no semantic meaning). - xit("should understand extraneous blocks", () => { - const source = unpad(` - function a() { - var f = 25; - function b() { - { - var f = "wow"; - } - function c() { - f.bar(); - } - c(); - c(); - } - function d() { - bar(f); - } - d(); - d(); - b(); - b(); - } - `); - - const expected = unpad(` - function a() { - function b() { - {} - function c() { - "wow".bar(); - } - c(); - c(); - } - function d() { - bar(25); - } - d(); - d(); - b(); - b(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should understand closures", () => { - const source = unpad(` - function a() { - var f = 25; - function b() { - var f = "wow"; - function c() { - f.bar(); - } - c(); - c(); - } - function d() { - bar(f); - } - d(); - d(); - b(); - b(); - } - `); - - const expected = unpad(` - function a() { - function b() { - function c() { - "wow".bar(); - } - c(); - c(); - } - function d() { - bar(25); - } - d(); - d(); - b(); - b(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should handle vars in if statements", () => { - const source = unpad(` - function a() { - if (x()) { - var foo = 1; - } - bar(foo); - } - `); - - const expected = unpad(` - function a() { - if (x()) { - var foo = 1; - } - bar(foo); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should handle vars in if statements 2", () => { - const source = unpad(` - function a() { - if (x()) var foo = 1; - bar(foo); - } - `); - - const expected = unpad(` - function a() { - if (x()) var foo = 1; - bar(foo); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should handle vars in for statements", () => { - const source = unpad(` - function a() { - for (;;) var foo = 1; - bar(foo); - } - `); - - const expected = unpad(` - function a() { - for (;;) var foo = 1; - bar(foo); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should handle for statements 2", () => { - const source = unpad(` - function a() { - for (;;) { - var foo = 1; - bar(foo); - } - } - `); - - const expected = unpad(` - function a() { - for (;;) { - bar(1); - } - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should remove binding and assignment", () => { - const source = unpad(` - function a() { - var a, b, c; - a = 1; - b = 2; - } - `); - - const expected = unpad(` - function a() {} - `); - - expect(transform(source)).toBe(expected); - }); - - it("should nore remove binding and assignment if the value is used", () => { - const source = unpad(` - function a() { - var x = 1; - while (a) wow = x += 1; - } - `); - - const expected = unpad(` - function a() { - var x = 1; - while (a) wow = x += 1; - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should keep side-effectful assignment values", () => { - const source = unpad(` - function a() { - var x; - x = wow(); - } - `); - - const expected = unpad(` - function a() { - wow(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not evaluate this binary expression to truthy", () => { - const source = unpad(` - function boo() { - var bar = foo || []; - if (!bar || baz.length === 0) { - return 'wow'; - } - } - `); - - const expected = unpad(` - function boo() { - var bar = foo || []; - if (!bar || baz.length === 0) { - return 'wow'; - } - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("eval the following to false", () => { - const source = unpad(` - function bar () { - var x = foo || 'boo'; - bar = x === 'wow' ? ' ' + z : ''; - } - `); - - const expected = unpad(` - function bar() { - var x = foo || 'boo'; - bar = x === 'wow' ? ' ' + z : ''; - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should get rid of the constant violations", () => { - const source = unpad(` - function bar () { - var x = foo(); - x = bar(); - } - `); - - const expected = unpad(` - function bar() { - foo(); - - bar(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should remove names from NFE", () => { - const source = unpad(` - function bar() { - return function wow() { - return boo(); - }; - } - `); - - const expected = unpad(` - function bar() { - return function () { - return boo(); - }; - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not remove names from NFE when referenced", () => { - const source = unpad(` - function bar() { - return function wow() { - return wow(); - }; - } - `); - - const expected = unpad(` - function bar() { - return function wow() { - return wow(); - }; - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should remove name from NFE when shadowed", () => { - const source = unpad(` - function bar() { - return function wow() { - var wow = foo; - wow(); - return wow; - }; - } - `); - - const expected = unpad(` - function bar() { - return function () { - var wow = foo; - wow(); - return wow; - }; - } - `); - - expect(transform(source)).toBe(expected); - }); - - // issue#81 - it("should NOT remove name from NFE when referenced - issue#81", () => { - const source = unpad(` - (function (require, module, exports) { - var Hub = function Hub(file, options) { - (0, _classCallCheck3.default)(this, Hub); - }; - module.exports = Hub; - })(require, module, exports); - `); - const expected = unpad(` - (function (require, module) { - module.exports = function Hub() { - (0, _classCallCheck3.default)(this, Hub); - }; - })(require, module, exports); - `); - expect(transform(source)).toBe(expected); - }); - - it("should remove name from NFE when replaced - issue#81", () => { - const source = unpad(` - (function () { - var x = function foo() {}; - module.exports = x; - })(); - `); - const expected = unpad(` - (function () { - module.exports = function () {}; - })(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should preserve fn names when keepFnName is true", () => { - const source = unpad(` - (function () { - function A() {} - exports.A = A; - var B = function B() {}; - exports.B = B; - onClick(function C() {}); - })(); - `); - const expected = unpad(` - (function () { - exports.A = function A() {}; - - exports.B = function B() {}; - onClick(function C() {}); - })(); - `); - expect(transform(source, { keepFnName: true })).toBe(expected); - }); - - it("should preserve class names when keepClassName is true", () => { - const source = unpad(` - (function () { - class A {} - exports.A = A; - var B = class B {}; - exports.B = B; - class AA {} new AA() - })(); - `); - const expected = unpad(` - (function () { - exports.A = class A {}; - - exports.B = class B {}; - new class AA {}(); - })(); - `); - expect(transform(source, { keepClassName: true })).toBe(expected); - }); - - // NCE = Named Class Expressions - it("should remove name from NCE", () => { - const source = unpad(` - var Foo = class Bar {}; - `); - const expected = unpad(` - var Foo = class {}; - `); - expect(transform(source)).toBe(expected); - }); - - it("should not remove referenced name from NCE", () => { - const source = unpad(` - var Foo = class Bar { - constructor() { - console.log(Bar); - } - }; - `); - const expected = source; - expect(transform(source)).toBe(expected); - }); - - // issue#78 - it("should not replace NCE with void 0 - issue#78", () => { - const source = unpad(` - (function() { - var B = class A { - constructor(x) { - console.log(x); - } - } - self.addEventListener(function (event) { - new B(event); - }); - })(); - `); - const expected = unpad(` - (function () { - var B = class { - constructor(x) { - console.log(x); - } - }; - self.addEventListener(function (event) { - new B(event); - }); - })(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should handle var decl with same name as class expr name", () => { - const source = unpad(` - (function () { - var A = class A { - constructor() { - this.class = A; - } - } - var B = class B {}; - exports.A = A; - exports.B = B; - })(); - `); - const expected = unpad(` - (function () { - exports.A = class A { - constructor() { - this.class = A; - } - }; - exports.B = class {}; - })(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should track purity", () => { - const source = unpad(` - function x(a) { - var l = a; - var x = l - foo(x); - } - `); - - const expected = unpad(` - function x(a) { - foo(a); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should latch on to exisiting vars", () => { - const source = unpad(` - function x(a) { - if (a) { - var x = a.wat; - foo(x); - } - var z = a.foo, b = b.bar; - return z + b; - } - `); - - const expected = unpad(` - function x(a) { - if (a) { - x = a.wat; - - foo(x); - } - var z = a.foo, - b = b.bar, - x; - return z + b; - } - `); - - expect(transform(source, { optimizeRawSize: true })).toBe(expected); - }); - - it("should put the var in the for in", () => { - const source = unpad(` - function x(a) { - var x; - wow(); - for (x in a) wow(); - } - `); - - const expected = unpad(` - function x(a) { - wow(); - for (var x in a) wow(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should put the var in the for in only when the var is alone", () => { - const source = unpad(` - function x(a) { - var x, y; - wow(y); - for (x in a) wow(y); - } - `); - - const expected = unpad(` - function x(a) { - var x, y; - wow(y); - for (x in a) wow(y); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("inlining should check name collision", () => { - const source = unpad(` - function foo() { - var a = 1; - var b = a; - function x(a) { - return a + b; - } - x(); - x(); - return a; - } - `); - - const expected = unpad(` - function foo() { - var a = 1; - var b = a; - function x(a) { - return a + b; - } - x(); - x(); - return a; - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("inlining should check name collision for expressions", () => { - const source = unpad(` - function foo() { - var a = c + d; - function x(c, d) { - return a + c + d; - } - x(); - x(); - } - `); - - const expected = unpad(` - function foo() { - var a = c + d; - function x(c, d) { - return a + c + d; - } - x(); - x(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should replace with empty statement if in body position 1", () => { - const source = unpad(` - function foo() { - var a = 0; - while (wat()) a += 1; - } - `); - - const expected = unpad(` - function foo() { - while (wat()); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should replace with empty statement if in body position 2", () => { - const source = unpad(` - function foo() { - while (wat()) 1; - } - `); - - const expected = unpad(` - function foo() { - while (wat()); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should replace with empty statement if in body position 3", () => { - const source = unpad(` - function foo() { - while (wat()) var x; - } - `); - - const expected = unpad(` - function foo() { - while (wat()); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("it should update binding path", () => { - const source = unpad(` - function foo() { - var key; - for (key in o); - for (key in o2); - } - `); - - const expected = unpad(` - function foo() { - for (var key in o); - for (key in o2); - } - `); - expect(transform(source)).toBe(expected); - }); - - xit("it should evaluate and remove falsy code", () => { - const source = unpad(` - foo(0 && bar()); - `); - const expected = unpad(` - foo(0); - `); - expect(transform(source)).toBe(expected); - }); - - it("should not move functions into other scopes", () => { - const source = unpad(` - function foo() { - var a = 1; - var bar = { x: {z: a, v: a} }; - var wow = { x: 1 }; - var baz = { x: function() {} }; - var boo = { x: { y: function () {} } }; - - function moo() { - var a = 2; - maa(wow, bar, baz, boo, a, a); - } - - return moo; - } - `); - - const expected = unpad(` - function foo() { - var a = 1; - var bar = { x: { z: a, v: a } }; - var wow = { x: 1 }; - var baz = { x: function () {} }; - var boo = { x: { y: function () {} } }; - - return function () { - var a = 2; - maa(wow, bar, baz, boo, a, a); - }; - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should preserve vars from the removed block", () => { - const source = unpad(` - if (0) {var a = foo()} - if (0) var b = foo(); - if (1) { } else { var c = foo() } - if (0) var d = bar(); else { } - `); - const expected = unpad(` - var a; - var b; - var c; - var d; - `); - - expect(transform(source)).toBe(expected); - }); - - it("should optimize alternate when empty consequent is replaced with alternate", () => { - const source = unpad(` - if (baz) { - } else { - let foo = 'bar'; - function foobar() {} - console.log('foo' + foo); - } - `); - const expected = unpad(` - if (!baz) { - console.log('foo' + 'bar'); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should transform simple switch statement", () => { - const source = unpad(` - switch (0) { - case 0: foo(); break; - case 1: bar(); break; - } - `); - const expected = unpad(` - foo(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should NOT optimize when one of the cases is not evaluate-able", () => { - const source = unpad(` - switch (a) { - case 1: - break; - } - switch (100) { - default: - foo(); - case a: - foo(); - break; - } - `); - const expected = source; - expect(transform(source)).toBe(expected); - }); - - it("should handle cases where there is no break", () => { - const source = unpad(` - switch (1) { - case 1: foo(); - case 2: bar(); - case 3: baz(); break; - case 4: foobarbaz(); - } - `); - const expected = unpad(` - foo(); - bar(); - baz(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should handle defaults", () => { - const source = unpad(` - switch (10) { - default: - foo(); - break; - case 1: - bar(); - break; - case 2: - baz(); - } - switch (5) { - case 1: - baz(); - break; - case 2: - bar(); - break; - default: - foo(); - } - `); - const expected = unpad(` - foo(); - - foo(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should predict break statement within blocks", () => { - const source = unpad(` - switch (1) { - case 1: - foo(); - if (true) break; - case 2: - bar(); - } - switch (1) { - case 1: - for(var i in x) { break } - case 2: - while(true) { break } - case 3: - foo(); - } - `); - - const expected = unpad(` - foo(); - var i; - - for (var i in x) { - break; - } - - while (true) { - break; - } - - foo(); - `); - - expect(transform(source)).toBe(expected); - }); - - it("should bail out when break label is above switch's scope", () => { - const source = unpad(` - x: switch (1) { - case 1: - break x; - } - y: switch (0) { - case 0: - while (true) { - break y; - } - } - z: switch (2) { - case 2: - { - break z; - } - } - `); - const expected = source; - expect(transform(source)).toBe(expected); - }); - - it("should NOT bail out when break label is under switch's scope", () => { - const source = unpad(` - switch (1) { - case 1: - x: while (true) { - break x; - } - } - `); - const expected = unpad(` - x: while (true) { - break x; - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should handle nested switch statements", () => { - const source = unpad(` - switch (1) { - case 1: - foo(); - switch (2) { - case 2: - bar(); - break; - } - break; - case 2: - baz(); + // issue#78 + thePlugin( + "should not replace NCE with void 0 - issue#78", + ` + (function() { + var B = class A { + constructor(x) { + console.log(x); + } } - `); - const expected = unpad(` - foo(); - - bar(); - `); - expect(transform(source)).toBe(expected); - }); + self.addEventListener(function (event) { + new B(event); + }); + })(); + `, + ` + (function () { + var B = class { + constructor(x) { + console.log(x); + } + }; + self.addEventListener(function (event) { + new B(event); + }); + })(); + ` + ); - it("should break correctly when there is a break statement after break", () => { - const source = unpad(` - switch (0) { - case 0: - foo(); - break; - bar(); - break; + thePlugin( + "should handle var decl with same name as class expr name", + ` + (function () { + var A = class A { + constructor() { + this.class = A; + } } - `); - const expected = unpad(` - foo(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should break correctly for the correct break statement", () => { - const source = unpad(` - switch (0) { - case 0: - foo(); - { - if (true) break; - bar(); - if (a) break; - } - case 1: - baz(); + var B = class B {}; + exports.A = A; + exports.B = B; + })(); + `, + ` + (function () { + exports.A = class A { + constructor() { + this.class = A; + } + }; + exports.B = class {}; + })(); + ` + ); + + thePlugin( + "should track purity", + ` + function x(a) { + var l = a; + var x = l + foo(x); + } + `, + ` + function x(a) { + foo(a); + } + ` + ); + + thePlugin( + "should latch on to exisiting vars", + ` + function x(a) { + if (a) { + var x = a.wat; + foo(x); + } + var z = a.foo, b = b.bar; + return z + b; + } + `, + ` + function x(a) { + if (a) { + x = a.wat; + + foo(x); + } + var z = a.foo, + b = b.bar, + x; + return z + b; + } + `, + { + plugins: [[deadcode, { optimizeRawSize: true }]] + } + ); + + thePlugin( + "should put the var in the for in", + ` + function x(a) { + var x; + wow(); + for (x in a) wow(); + } + `, + ` + function x(a) { + wow(); + for (var x in a) wow(); + } + ` + ); + + thePlugin( + "should put the var in the for in only when the var is alone", + ` + function x(a) { + var x, y; + wow(y); + for (x in a) wow(y); + } + `, + ` + function x(a) { + var x, y; + wow(y); + for (x in a) wow(y); + } + ` + ); + + thePlugin( + "inlining should check name collision", + ` + function foo() { + var a = 1; + var b = a; + function x(a) { + return a + b; } - `); - const expected = unpad(` - foo(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should bail out for runtime evaluated if(x) break", () => { - const source = unpad(` - switch (0) { - case 0: - foo(); - if (a) break; - case 1: - bar(); + x(); + x(); + return a; + } + `, + ` + function foo() { + var a = 1; + var b = a; + function x(a) { + return a + b; } - `); - const expected = source; - expect(transform(source)).toBe(expected); - }); + x(); + x(); + return a; + } + ` + ); + + thePlugin( + "inlining should check name collision for expressions", + ` + function foo() { + var a = c + d; + function x(c, d) { + return a + c + d; + } + x(); + x(); + } + `, + ` + function foo() { + var a = c + d; + function x(c, d) { + return a + c + d; + } + x(); + x(); + } + ` + ); + + thePlugin( + "should replace with empty statement if in body position 1", + ` + function foo() { + var a = 0; + while (wat()) a += 1; + } + `, + ` + function foo() { + while (wat()); + } + ` + ); + + thePlugin( + "should replace with empty statement if in body position 2", + ` + function foo() { + while (wat()) 1; + } + `, + ` + function foo() { + while (wat()); + } + ` + ); + + thePlugin( + "should replace with empty statement if in body position 3", + ` + function foo() { + while (wat()) var x; + } + `, + ` + function foo() { + while (wat()); + } + ` + ); + + thePlugin( + "it should update binding path", + ` + function foo() { + var key; + for (key in o); + for (key in o2); + } + `, + ` + function foo() { + for (var key in o); + for (key in o2); + } + ` + ); + + thePlugin.skip( + "it should evaluate and remove falsy code", + ` + foo(0 && bar()); + `, + ` + foo(0); + ` + ); + + thePlugin( + "should not move functions into other scopes", + ` + function foo() { + var a = 1; + var bar = { x: {z: a, v: a} }; + var wow = { x: 1 }; + var baz = { x: function() {} }; + var boo = { x: { y: function () {} } }; - it("should NOT bail out for runtime evaluated if(x) break inside loop", () => { - const source = unpad(` - switch (0) { - case 0: - foo(); - while (1) { if (x) break; } - case 1: - bar(); + function moo() { + var a = 2; + maa(wow, bar, baz, boo, a, a); } - `); - const expected = unpad(` - foo(); - while (1) { - if (x) break; - } - - bar(); - `); - expect(transform(source)).toBe(expected); - }); - it("should optimize While statements", () => { - const source = unpad(` - while (false) { + return moo; + } + `, + ` + function foo() { + var a = 1; + var bar = { x: { z: a, v: a } }; + var wow = { x: 1 }; + var baz = { x: function () {} }; + var boo = { x: { y: function () {} } }; + + return function () { + var a = 2; + maa(wow, bar, baz, boo, a, a); + }; + } + ` + ); + + thePlugin( + "should preserve vars from the removed block", + ` + if (0) {var a = foo()} + if (0) var b = foo(); + if (1) { } else { var c = foo() } + if (0) var d = bar(); else { } + `, + ` + var a; + var b; + var c; + var d; + ` + ); + + thePlugin( + "should optimize alternate when empty consequent is replaced with alternate", + ` + if (baz) { + } else { + let foo = 'bar'; + function foobar() {} + console.log('foo' + foo); + } + `, + ` + if (!baz) { + console.log('foo' + 'bar'); + } + ` + ); + + thePlugin( + "should transform simple switch statement", + ` + switch (0) { + case 0: foo(); break; + case 1: bar(); break; + } + `, + ` + foo(); + ` + ); + + thePlugin( + "should NOT optimize when one of the cases is not evaluate-able", + ` + switch (a) { + case 1: + break; + } + switch (100) { + default: foo(); - } - while (true) { + case a: + foo(); + break; + } + ` + ); + + thePlugin( + "should handle cases where there is no break", + ` + switch (1) { + case 1: foo(); + case 2: bar(); + case 3: baz(); break; + case 4: foobarbaz(); + } + `, + ` + foo(); + bar(); + baz(); + ` + ); + + thePlugin( + "should handle defaults", + ` + switch (10) { + default: + foo(); + break; + case 1: bar(); - } - while (x) { + break; + case 2: baz(); - } - `); - const expected = unpad(` - while (true) { - bar(); - } - while (x) { + } + switch (5) { + case 1: baz(); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should optimize For statements", () => { - const source = unpad(` - for (var i = 0; i < 8; i++) { + break; + case 2: + bar(); + break; + default: foo(); - } - for (; true;) { + } + `, + ` + foo(); + + foo(); + ` + ); + + thePlugin( + "should predict break statement within blocks", + ` + switch (1) { + case 1: + foo(); + if (true) break; + case 2: bar(); - } - for (; false;) { + } + switch (1) { + case 1: + for(var i in x) { break } + case 2: + while(true) { break } + case 3: + foo(); + } + `, + ` + foo(); + var i; + + for (var i in x) { + break; + } + + while (true) { + break; + } + + foo(); + ` + ); + + thePlugin( + "should bail out when break label is above switch's scope", + ` + x: switch (1) { + case 1: + break x; + } + y: switch (0) { + case 0: + while (true) { + break y; + } + } + z: switch (2) { + case 2: + { + break z; + } + } + ` + ); + + thePlugin( + "should NOT bail out when break label is under switch's scope", + ` + switch (1) { + case 1: + x: while (true) { + break x; + } + } + `, + ` + x: while (true) { + break x; + } + ` + ); + + thePlugin( + "should handle nested switch statements", + ` + switch (1) { + case 1: + foo(); + switch (2) { + case 2: + bar(); + break; + } + break; + case 2: baz(); - } - `); - const expected = unpad(` - for (var i = 0; i < 8; i++) { + } + `, + ` + foo(); + + bar(); + ` + ); + + thePlugin( + "should break correctly when there is a break statement after break", + ` + switch (0) { + case 0: foo(); - } - for (;;) { + break; bar(); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should optimize dowhile statements", () => { - const source = unpad(` - do { + break; + } + `, + ` + foo(); + ` + ); + + thePlugin( + "should break correctly for the correct break statement", + ` + switch (0) { + case 0: foo(); - } while (1); - do { - bar() - } while (0); - do { + { + if (true) break; + bar(); + if (a) break; + } + case 1: baz(); - } while (a); - `); - const expected = unpad(` - do { + } + `, + ` + foo(); + ` + ); + + thePlugin( + "should bail out for runtime evaluated if(x) break", + ` + switch (0) { + case 0: foo(); - } while (1); - { + if (a) break; + case 1: bar(); - } - do { - baz(); - } while (a); - `); - expect(transform(source)).toBe(expected); - }); - - it("should not evaluate to false and remove conditional", () => { - const source = unpad(` - function foo(obj) { - return obj && typeof obj === 'object' ? x() : obj; - } - `); - const expected = unpad(` - function foo(obj) { - return obj && typeof obj === 'object' ? x() : obj; - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should extract vars from the removed switch statement", () => { - const source = unpad(` - switch (0) { - case 1: - var a = 5; - var b = 6; - } - switch (0) { - default: - var a = 1; - var b = 2; - } - `); - const expected = unpad(` - var a, b; - var a, b; - - var a = 1; - var b = 2; - `); - expect(transform(source)).toBe(expected); - }); - - it("should handle side-effecty things in cases", () => { - const source = unpad(` - let i = 0; - let bar = () => console.log('foo'); - switch (1) { - case ++i: - foo(); - break; - case bar(): - baz(); - } - `); - const expected = source; - expect(transform(source)).toBe(expected); - }); - - it("should preserve names in NFEs", () => { - const source = unpad(` - function method() { - var removeListeners = function removeListeners() { - log(removeListeners); - }; - removeListeners(); - } - `); - - const expected = unpad(` - function method() { - (function removeListeners() { - log(removeListeners); - })(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - // https://github.com/babel/babili/issues/130 - it("should not convert expression to expression during replace issue#130", () => { - const source = unpad(` - function outer() { - const inner = (d) => d.x; - return inner; - } - `); - const expected = unpad(` - function outer() { - return d => d.x; - } - `); - expect(transform(source)).toBe(expected); - }); - - // https://github.com/babel/babili/issues/151 - it("should fix issue#151 - array patterns and object patterns", () => { - const source = unpad(` - const me = lyfe => { - const [swag] = lyfe; - return swag; - }; - `); - const expected = source; - expect(transform(source)).toBe(expected); - }); - - // https://github.com/babel/babili/issues/151 - it("should fix issue#151 - array patterns and object patterns 2", () => { - const source = unpad(` - const me = lyfe => { - const [swag, yolo] = lyfe; - return swag && yolo; - }; - `); - const expected = source; - expect(transform(source)).toBe(expected); - }); - - // https://github.com/babel/babili/issues/232 - it("should fix issue#232 - array patterns and object patterns with non constant init", () => { - const source = unpad(` - const a = { - lol: input => { - const [hello, world] = input.split('|'); - if (hello === 't' || hello === 'top') { - return 'top'; - } - return 'bottom'; - } - }; - `); - const expected = source; - expect(transform(source)).toBe(expected); - }); - - // https://github.com/babel/babili/issues/232 - it("should fix issue#232 - array & object patterns with non-constant init", () => { - const source = unpad(` - function foo() { - const { bar1, bar2 } = baz(); - return bar1; - } - `); - const expected = source; - expect(transform(source)).toBe(expected); - }); - - it("should preserve variabledeclarations(var) after completion statements", () => { - const source = unpad(` - function foo() { - a = 1; - return a; - var a; - } - `); - - const expected = source; - - expect(transform(source)).toBe(expected); - }); - - it("should NOT preserve variabledeclarations(let) after completion statements", () => { - const source = unpad(` - function foo() { - a = 1; - b = 2; - return a + b; - let a, b; - } - `); + } + ` + ); + + thePlugin( + "should NOT bail out for runtime evaluated if(x) break inside loop", + ` + switch (0) { + case 0: + foo(); + while (1) { if (x) break; } + case 1: + bar(); + } + `, + ` + foo(); + while (1) { + if (x) break; + } + + bar(); + ` + ); + + thePlugin( + "should optimize While statements", + ` + while (false) { + foo(); + } + while (true) { + bar(); + } + while (x) { + baz(); + } + `, + ` + while (true) { + bar(); + } + while (x) { + baz(); + } + ` + ); + + thePlugin( + "should optimize For statements", + ` + for (var i = 0; i < 8; i++) { + foo(); + } + for (; true;) { + bar(); + } + for (; false;) { + baz(); + } + `, + ` + for (var i = 0; i < 8; i++) { + foo(); + } + for (;;) { + bar(); + } + ` + ); + + thePlugin( + "should optimize dowhile statements", + ` + do { + foo(); + } while (1); + do { + bar() + } while (0); + do { + baz(); + } while (a); + `, + ` + do { + foo(); + } while (1); + { + bar(); + } + do { + baz(); + } while (a); + ` + ); + + thePlugin( + "should not evaluate to false and remove conditional", + ` + function foo(obj) { + return obj && typeof obj === 'object' ? x() : obj; + } + `, + ` + function foo(obj) { + return obj && typeof obj === 'object' ? x() : obj; + } + ` + ); + + thePlugin( + "should extract vars from the removed switch statement", + ` + switch (0) { + case 1: + var a = 5; + var b = 6; + } + switch (0) { + default: + var a = 1; + var b = 2; + } + `, + ` + var a, b; + var a, b; + + var a = 1; + var b = 2; + ` + ); + + thePlugin( + "should handle side-effecty things in cases", + ` + let i = 0; + let bar = () => console.log('foo'); + switch (1) { + case ++i: + foo(); + break; + case bar(): + baz(); + } + ` + ); + + thePlugin( + "should preserve names in NFEs", + ` + function method() { + var removeListeners = function removeListeners() { + log(removeListeners); + }; + removeListeners(); + } + `, + ` + function method() { + (function removeListeners() { + log(removeListeners); + })(); + } + ` + ); - const expected = unpad(` - function foo() { - a = 1; - b = 2; - return a + b; - } - `); + // https://github.com/babel/babili/issues/130 + thePlugin( + "should not convert expression to expression during replace issue#130", + ` + function outer() { + const inner = (d) => d.x; + return inner; + } + `, + ` + function outer() { + return d => d.x; + } + ` + ); - expect(transform(source)).toBe(expected); - }); + // https://github.com/babel/babili/issues/151 + thePlugin( + "should fix issue#151 - array patterns and object patterns", + ` + const me = lyfe => { + const [swag] = lyfe; + return swag; + }; + ` + ); - it("should not remove var from for..in/for..of statements", () => { - const source = unpad(` - function foo() { - for (var i in x) console.log("foo"); - for (var j of y) console.log("foo"); - } - `); - const expected = source; - expect(transform(source)).toBe(expected); - }); + // https://github.com/babel/babili/issues/151 + thePlugin( + "should fix issue#151 - array patterns and object patterns 2", + ` + const me = lyfe => { + const [swag, yolo] = lyfe; + return swag && yolo; + }; + ` + ); - it("should not remove var from for..await statements", () => { - const source = unpad(` - async function foo() { - for await (var x of y) console.log("bar"); - } - `); - const expected = source; - expect( - transform( - source, - {}, - { - parserOpts: { - plugins: ["asyncGenerators"] - } + // https://github.com/babel/babili/issues/232 + thePlugin( + "should fix issue#232 - array patterns and object patterns with non constant init", + ` + const a = { + lol: input => { + const [hello, world] = input.split('|'); + if (hello === 't' || hello === 'top') { + return 'top'; } - ) - ).toBe(expected); - }); - it("should remove empty statements when children of block", () => { - const source = unpad(` - (function () { - function foo() {}; - function bar() {}; - function baz() {}; - function ban() {}; - function quux() {}; - function cake() {}; - })(); - `); - const expected = unpad(` - (function () {})(); - `); - expect(transform(source)).toBe(expected); - }); + return 'bottom'; + } + }; + ` + ); - it("should NOT remove fn params for setters", () => { - const source = unpad(` - function foo() { - var x = { - set a(b) {} - }; - class A { - set c(d) { - x.a = 5; - } + // https://github.com/babel/babili/issues/232 + thePlugin( + "should fix issue#232 - array & object patterns with non-constant init", + ` + function foo() { + const { bar1, bar2 } = baz(); + return bar1; + } + ` + ); + + thePlugin( + "should preserve variabledeclarations(var) after completion statements", + ` + function foo() { + a = 1; + return a; + var a; + } + ` + ); + + thePlugin( + "should NOT preserve variabledeclarations(let) after completion statements", + ` + function foo() { + a = 1; + b = 2; + return a + b; + let a, b; + } + `, + ` + function foo() { + a = 1; + b = 2; + return a + b; + } + ` + ); + + thePlugin( + "should not remove var from for..in/for..of statements", + ` + function foo() { + for (var i in x) console.log("foo"); + for (var j of y) console.log("foo"); + } + ` + ); + + thePlugin( + "should not remove var from for..await statements", + ` + async function foo() { + for await (var x of y) console.log("bar"); + } + `, + { + parserOpts: { + plugins: ["asyncGenerators"] + } + } + ); + + thePlugin( + "should remove empty statements when children of block", + ` + (function () { + function foo() {}; + function bar() {}; + function baz() {}; + function ban() {}; + function quux() {}; + function cake() {}; + })(); + `, + ` + (function () {})(); + ` + ); + + thePlugin( + "should NOT remove fn params for setters", + ` + function foo() { + var x = { + set a(b) {} + }; + class A { + set c(d) { + x.a = 5; } - return new A(); } - `); - expect(transform(source)).toBe(source); - }); + return new A(); + } + ` + ); // https://github.com/babel/babili/issues/265 - it("should not remove return void 0; statement if inside a loop", () => { - const source = unpad(` - function getParentConditionalPath(path) { - let parentPath; - while (parentPath = path.parentPath) { - if (parentPath.isIfStatement() || parentPath.isConditionalExpression()) { - if (path.key === "test") { - return; - } else { - return parentPath; - } + thePlugin( + "should not remove return void 0; statement if inside a loop", + ` + function getParentConditionalPath(path) { + let parentPath; + while (parentPath = path.parentPath) { + if (parentPath.isIfStatement() || parentPath.isConditionalExpression()) { + if (path.key === "test") { + return; } else { - path = parentPath; + return parentPath; } + } else { + path = parentPath; } } - `); - - expect(transform(source)).toBe(source); - }); + } + ` + ); // https://github.com/babel/babili/issues/265 it("should integrate with simplify plugin changing scopes", () => { @@ -2321,393 +2211,381 @@ describe("dce-plugin", () => { expect(transformWithSimplify(source)).toBe(expected); }); - it("should not remove params from functions containing direct eval", () => { - const source = unpad(` - function a(b, c, d) { - eval(";"); - return b; - } - function b(c, d, e) { - (1, eval)(";"); - return c; - } - `); + thePlugin( + "should not remove params from functions containing direct eval", + ` + function a(b, c, d) { + eval(";"); + return b; + } + function b(c, d, e) { + (1, eval)(";"); + return c; + } + `, + ` + function a(b, c, d) { + eval(";"); + return b; + } + function b(c) { + (1, eval)(";"); + return c; + } + ` + ); + + thePlugin( + "should not remove params/vars from functions containing direct eval", + ` + function foo(bar, baz) { + function foox(a, b, c) { + x.then((data, unused) => { + let unused1; + eval(data); + foox1(); + { + var unused2; + } + }); - const expected = unpad(` - function a(b, c, d) { - eval(";"); - return b; + function foox1(unused) { + console.log("foox1"); + } } - function b(c) { - (1, eval)(";"); - return c; + function fooy(unused1, unused2) { + console.log("fooy"); } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not remove params/vars from functions containing direct eval", () => { - const source = unpad(` - function foo(bar, baz) { - function foox(a, b, c) { - x.then((data, unused) => { - let unused1; - eval(data); - foox1(); - { - var unused2; - } - }); - - function foox1(unused) { - console.log("foox1"); + } + `, + ` + function foo(bar, baz) { + function foox(a, b, c) { + x.then((data, unused) => { + let unused1; + eval(data); + foox1(); + { + var unused2; } - } - function fooy(unused1, unused2) { - console.log("fooy"); - } - } - `); - - const expected = unpad(` - function foo(bar, baz) { - function foox(a, b, c) { - x.then((data, unused) => { - let unused1; - eval(data); - foox1(); - { - var unused2; - } - }); + }); - function foox1() { - console.log("foox1"); - } - } - function fooy() { - console.log("fooy"); + function foox1() { + console.log("foox1"); } } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not optimize/remove vars from functions containing direct eval", () => { - const source = unpad(` - function foo() { - bar(); + function fooy() { + console.log("fooy"); + } + } + ` + ); - var x = 5; - return x; + thePlugin( + "should not optimize/remove vars from functions containing direct eval", + ` + function foo() { + bar(); - function bar() { - eval(";"); - return 5; - } + var x = 5; + return x; - function baz() { - let x = 10; - return x; - } + function bar() { + eval(";"); + return 5; } - `); - - const expected = unpad(` - function foo() { - bar(); - var x = 5; + function baz() { + let x = 10; return x; - - function bar() { - eval(";"); - return 5; - } - - function baz() { - return 10; - } } - `); + } + `, + ` + function foo() { + bar(); - expect(transform(source)).toBe(expected); - }); + var x = 5; + return x; - it("should impure expressions in confidently evaluated if statements", () => { - const source = unpad(` - if (a.b(), true) { - foo(); + function bar() { + eval(";"); + return 5; } - `); - const expected = unpad(` - a.b(); - - foo(); - `); - expect(transform(source)).toBe(expected); - }); - it("should extract all necessary things from if statements", () => { - const source = unpad(` - if (a.b(), false) { - var foo = foo1; - foo(); - } else if (b.c(), true) { - var bar = bar1; - bar(); - } else { - var baz = baz1; - baz(); + function baz() { + return 10; } - `); - const expected = unpad(` - a.b(); - b.c(); + } + ` + ); + thePlugin( + "should impure expressions in confidently evaluated if statements", + ` + if (a.b(), true) { + foo(); + } + `, + ` + a.b(); + + foo(); + ` + ); + + thePlugin( + "should extract all necessary things from if statements", + ` + if (a.b(), false) { + var foo = foo1; + foo(); + } else if (b.c(), true) { var bar = bar1; bar(); - var baz; - var foo; - `); - expect(transform(source)).toBe(expected); - }); - - it("should not remove vars after return statement", () => { - const source = unpad(` - function f() { + } else { + var baz = baz1; + baz(); + } + `, + ` + a.b(); + b.c(); + + var bar = bar1; + bar(); + var baz; + var foo; + ` + ); + + thePlugin( + "should not remove vars after return statement", + ` + function f() { + return x; + var x = 1; + } + `, + ` + function f() { + return void 0; + } + ` + ); + + thePlugin( + "should not remove vars after return statement #2", + ` + var x = 0; + function f1(){ + function f2(){ return x; - var x = 1; - } - `); - - const expected = unpad(` - function f() { - return void 0; + }; + return f2(); + var x = 1; + } + `, + ` + var x = 0; + function f1() { + return function () { + return x; + }(); + var x = 1; + } + ` + ); + + thePlugin( + "should not remove vars after return statement #3", + ` + function foo() { + bar = x; + var x = 1; + } + `, + ` + function foo() { + bar = void 0; + } + ` + ); + + thePlugin( + "should deopt for impure tests", + ` + function foo() { + do { + bar(); + } while ((bar(), false)); + for (; bar(), false;) { + bar(); } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not remove vars after return statement #2", () => { - const source = unpad(` - var x = 0; - function f1(){ - function f2(){ - return x; - }; - return f2(); - var x = 1; + while (bar(), false) { + bar(); } - `); + } + ` + ); - const expected = unpad(` - var x = 0; - function f1() { - return function () { - return x; - }(); - var x = 1; - } - `); + thePlugin( + "should handle confident do..while with break statements", + ` + function foo() { + do { + if (x) break; + } while (false); - expect(transform(source)).toBe(expected); - }); + do break; while (false); - it("should not remove vars after return statement #3", () => { - const source = unpad(` - function foo() { - bar = x; - var x = 1; - } - `); + bar0: do break; while (false); - const expected = unpad(` - function foo() { - bar = void 0; - } - `); + bar1: do break bar1; while (false); - expect(transform(source)).toBe(expected); - }); + bar2: do { + if (y) break; + } while (false); - it("should deopt for impure tests", () => { - const source = unpad(` - function foo() { - do { - bar(); - } while ((bar(), false)); - for (; bar(), false;) { - bar(); - } - while (bar(), false) { - bar(); - } - } - `); - expect(transform(source)).toBe(source); - }); + bar3: do { + if (y) break bar3; + } while (false); - it("should handle confident do..while with break statements", () => { - const source = unpad(` - function foo() { - do { + bar4: do { + while (baz()) { if (x) break; - } while (false); - - do break; while (false); - - bar0: do break; while (false); + } + } while (false); - bar1: do break bar1; while (false); + bar5: do { + while (baz()) { + if (x) break bar5; + } + } while (false); + } + `, + ` + function foo() { + do { + if (x) break; + } while (false); - bar2: do { - if (y) break; - } while (false); + bar1: do break bar1; while (false); - bar3: do { - if (y) break bar3; - } while (false); + bar2: do { + if (y) break; + } while (false); - bar4: do { - while (baz()) { - if (x) break; - } - } while (false); + bar3: do { + if (y) break bar3; + } while (false); - bar5: do { - while (baz()) { - if (x) break bar5; - } - } while (false); - } - `); - const expected = unpad(` - function foo() { - do { + bar4: { + while (baz()) { if (x) break; - } while (false); - - bar1: do break bar1; while (false); - - bar2: do { - if (y) break; - } while (false); - - bar3: do { - if (y) break bar3; - } while (false); - - bar4: { - while (baz()) { - if (x) break; - } } - - bar5: do { - while (baz()) { - if (x) break bar5; - } - } while (false); } - `); - expect(transform(source)).toBe(expected); - }); - it("should handle confident do..while with continue statements", () => { - const source = unpad(` - function foo() { - do { - if (x) continue; - } while (false); + bar5: do { + while (baz()) { + if (x) break bar5; + } + } while (false); + } + ` + ); - do continue; while (false); + thePlugin( + "should handle confident do..while with continue statements", + ` + function foo() { + do { + if (x) continue; + } while (false); - bar0: do continue; while (false); + do continue; while (false); - bar1: do continue bar1; while (false); + bar0: do continue; while (false); - bar2: do { - if (y) continue; - } while (false); + bar1: do continue bar1; while (false); - bar3: do { - if (y) continue bar3; - } while (false); + bar2: do { + if (y) continue; + } while (false); - bar4: do { - while (baz()) { - if (x) continue; - } - } while (false); + bar3: do { + if (y) continue bar3; + } while (false); - bar5: do { - while (baz()) { - if (x) continue bar5; - } - } while (false); - } - `); - const expected = unpad(` - function foo() { - do { + bar4: do { + while (baz()) { if (x) continue; - } while (false); + } + } while (false); - do continue; while (false); + bar5: do { + while (baz()) { + if (x) continue bar5; + } + } while (false); + } + `, + ` + function foo() { + do { + if (x) continue; + } while (false); - bar0: do continue; while (false); + do continue; while (false); - bar1: do continue bar1; while (false); + bar0: do continue; while (false); - bar2: do { - if (y) continue; - } while (false); + bar1: do continue bar1; while (false); - bar3: do { - if (y) continue bar3; - } while (false); + bar2: do { + if (y) continue; + } while (false); - bar4: { - while (baz()) { - if (x) continue; - } - } + bar3: do { + if (y) continue bar3; + } while (false); - bar5: do { - while (baz()) { - if (x) continue bar5; - } - } while (false); + bar4: { + while (baz()) { + if (x) continue; + } } - `); - expect(transform(source)).toBe(expected); - }); - it("should remove unnecessary use strict directives", () => { - const source = unpad(` - function foo() { - "use strict"; - function bar() { - "use strict"; - bar(); + bar5: do { + while (baz()) { + if (x) continue bar5; } - bar.call(); - } - `); - const expected = unpad(` - function foo() { + } while (false); + } + ` + ); + + thePlugin( + "should remove unnecessary use strict directives", + ` + function foo() { + "use strict"; + function bar() { "use strict"; + bar(); + } + bar.call(); + } + `, + ` + function foo() { + "use strict"; - function bar() { - bar(); - } - bar.call(); + function bar() { + bar(); } - `); - expect(transform(source)).toBe(expected); - }); + bar.call(); + } + ` + ); }); diff --git a/packages/babel-plugin-minify-flip-comparisons/__tests__/flip-comparisons-test.js b/packages/babel-plugin-minify-flip-comparisons/__tests__/flip-comparisons-test.js index 771130f42..8c8aa75d9 100644 --- a/packages/babel-plugin-minify-flip-comparisons/__tests__/flip-comparisons-test.js +++ b/packages/babel-plugin-minify-flip-comparisons/__tests__/flip-comparisons-test.js @@ -1,95 +1,101 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); -const unpad = require("../../../utils/unpad"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("flip-comparisons", () => { - it("should merge two conditionals if the same consequent", () => { - const source = unpad(` - x === null ? undefined : x === undefined ? undefined : x ? foo(x) : wat(); - `); - - const expected = unpad(` - null === x ? undefined : x === undefined ? undefined : x ? foo(x) : wat(); - `); - - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should merge two conditionals if the same consequent", + ` + x === null ? undefined : x === undefined ? undefined : x ? foo(x) : wat(); + `, + ` + null === x ? undefined : x === undefined ? undefined : x ? foo(x) : wat(); + ` + ); - it("should put values first in binary expressions", () => { - const source = "a === 1;"; - const expected = "1 === a;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should put values first in binary expressions", + ` + a === 1; + `, + ` + 1 === a; + ` + ); - it("should put constants first in binary expressions", () => { - const source = "a === -1;"; - const expected = "-1 === a;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should put constants first in binary expressions", + ` + a === -1; + `, + ` + -1 === a; + ` + ); - it("should put pures first in binary expressions 2", () => { - const source = "a === null;"; - const expected = "null === a;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should put pures first in binary expressions 2", + ` + a === null; + `, + ` + null === a; + ` + ); - it("should put pures first in binary expressions 3", () => { - const source = unpad(` - function foo() { - if (foo !== null) { - var bar; - bar = baz; - } - x(); - return x; + thePlugin( + "should put pures first in binary expressions 3", + ` + function foo() { + if (foo !== null) { + var bar; + bar = baz; } - `); - const expected = unpad(` - function foo() { - if (null !== foo) { - var bar; - bar = baz; - } - x(); - return x; + x(); + return x; + } + `, + ` + function foo() { + if (null !== foo) { + var bar; + bar = baz; } - `); - expect(transform(source)).toBe(expected); - }); - - it("should put pures first in binary expressions 2", () => { - const source = "a === {};"; - const expected = "({}) === a;"; - expect(transform(source)).toBe(expected); - }); - - it("should put constants first", () => { - const source = unpad(` - x * 100; - x + 100; - x - 100; - x / 100; - x > 100; - x === void 0; - `); + x(); + return x; + } + ` + ); - const expected = unpad(` - 100 * x; - x + 100; - x - 100; - x / 100; - 100 < x; - void 0 === x; - `); + thePlugin( + "should put pures first in binary expressions 2", + ` + a === {}; + `, + ` + ({}) === a; + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should put constants first", + ` + x * 100; + x + 100; + x - 100; + x / 100; + x > 100; + x === void 0; + `, + ` + 100 * x; + x + 100; + x - 100; + x / 100; + 100 < x; + void 0 === x; + ` + ); }); diff --git a/packages/babel-plugin-minify-guarded-expressions/__tests__/guarded-expressions-test.js b/packages/babel-plugin-minify-guarded-expressions/__tests__/guarded-expressions-test.js index 4067e985d..92b4a1414 100644 --- a/packages/babel-plugin-minify-guarded-expressions/__tests__/guarded-expressions-test.js +++ b/packages/babel-plugin-minify-guarded-expressions/__tests__/guarded-expressions-test.js @@ -1,129 +1,63 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); -const unpad = require("../../../utils/unpad"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("guarded-expressions-plugin", () => { - it("should flip logical expressions", () => { - const source = unpad(` - !x && foo(); - `); - - const expected = unpad(` - x || foo(); - `); - - expect(transform(source).trim()).toBe(expected.trim()); - }); - - it("should simplify falsy logical expressions", function() { - let source = unpad(` - alert(0 && new Foo()); - `); - let expected = unpad(` - alert(0); - `); - expect(transform(source)).toBe(expected); - - source = unpad(` - if (0 && something()) for(;;); - `); - expected = unpad(` - if (0) for (;;); - `); - expect(transform(source)).toBe(expected); - - source = unpad(` - alert(false && new Foo()); - `); - expected = unpad(` - alert(false); - `); - expect(transform(source)).toBe(expected); - - source = unpad(` - alert(undefined && new Foo()); - `); - expected = unpad(` - alert(undefined); - `); - expect(transform(source)).toBe(expected); - - source = unpad(` - alert(null && new Foo()); - `); - expected = unpad(` - alert(null); - `); - expect(transform(source)).toBe(expected); - - source = unpad(` - alert("" && new Foo()); - `); - expected = unpad(` - alert(""); - `); - expect(transform(source)).toBe(expected); - - source = unpad(` - alert(new Foo() || false); - `); - expected = unpad(` - alert(new Foo() || false); - `); - expect(transform(source)).toBe(expected); - }); - - it("should simplify truthy expressions", () => { - let source = unpad(` - alert(1 && new Bar()); - `); - let expected = unpad(` - alert(new Bar()); - `); - expect(transform(source)).toBe(expected); - - source = unpad(` - alert(true && new Bar()); - `); - expected = unpad(` - alert(new Bar()); - `); - expect(transform(source)).toBe(expected); - - source = unpad(` - alert("hello" && new Bar()); - `); - expected = unpad(` - alert(new Bar()); - `); - expect(transform(source)).toBe(expected); - - source = unpad(` - alert(!false && new Bar()); - `); - expected = unpad(` - alert(new Bar()); - `); - expect(transform(source)).toBe(expected); - }); - - it("should not remove reachable impure statements", () => { - let source = unpad(` - a && void alert('Side effect'); - `); - expect(transform(source)).toBe(source); - - source = unpad(` - alert(func() || true); - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should flip logical expressions", + ` + !x && foo(); + `, + ` + x || foo(); + ` + ); + + thePlugin( + "should simplify falsy logical expressions", + ` + alert(0 && new Foo()); + if (0 && something()) for(;;); + alert(false && new Foo()); + alert(undefined && new Foo()); + alert(null && new Foo()); + alert("" && new Foo()); + alert(new Foo() || false); + `, + ` + alert(0); + if (0) for (;;); + alert(false); + alert(undefined); + alert(null); + alert(""); + alert(new Foo() || false); + ` + ); + + thePlugin( + "should simplify truthy expressions", + ` + alert(1 && new Bar()); + alert(true && new Bar()); + alert("hello" && new Bar()); + alert(!false && new Bar()); + `, + ` + alert(new Bar()); + alert(new Bar()); + alert(new Bar()); + alert(new Bar()); + ` + ); + + thePlugin( + "should not remove reachable impure statements", + ` + a && void alert('Side effect'); + alert(func() || true); + ` + ); }); diff --git a/packages/babel-plugin-minify-infinity/__tests__/infinity-test.js b/packages/babel-plugin-minify-infinity/__tests__/infinity-test.js index 0fb5bd277..06dceeb94 100644 --- a/packages/babel-plugin-minify-infinity/__tests__/infinity-test.js +++ b/packages/babel-plugin-minify-infinity/__tests__/infinity-test.js @@ -1,93 +1,50 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); -const unpad = require("../../../utils/unpad"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("boolean-plugin", () => { - it("should convert infinity to division over 0", () => { - const source = unpad(` - Infinity; - `); - - const expected = unpad(` - 1 / 0; - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not convert infinity when its a property", () => { - const source = unpad(` - var x = { Infinity: 0 }; - `); - - const expected = unpad(` - var x = { Infinity: 0 }; - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not convert infinity when its a property", () => { - const source = unpad(` - x.Infinity; - `); - - const expected = unpad(` - x.Infinity; - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not convert infinity if its a assignment expression", () => { - const source = unpad(` - Infinity = 1; - `); - - const expected = unpad(` - Infinity = 1; - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not convert infinity when its destructed", () => { - const source = unpad(` - ({ Infinity } = 1); - [Infinity] = foo; - [...Infinity] = foo; - `); - - const expected = unpad(` - ({ Infinity } = 1); - [Infinity] = foo; - [...Infinity] = foo; - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not convert infinity when as a function params", () => { - const source = unpad(` - function a(Infinity) {} - function a(...Infinity) {} - function a({ Infinity }) {} - `); - - const expected = unpad(` - function a(Infinity) {} - function a(...Infinity) {} - function a({ Infinity }) {} - `); - - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should convert infinity to division over 0", + ` + Infinity; + `, + ` + 1 / 0; + ` + ); + + thePlugin( + "should not convert infinity when its a property", + ` + var x = { Infinity: 0 }; + x.Infinity; + ` + ); + + thePlugin( + "should not convert infinity if its a assignment expression", + ` + Infinity = 1; + ` + ); + + thePlugin( + "should not convert infinity when its destructed", + ` + ({ Infinity } = 1); + [Infinity] = foo; + [...Infinity] = foo; + ` + ); + + thePlugin( + "should not convert infinity when as a function params", + ` + function a(Infinity) {} + function a(...Infinity) {} + function a({ Infinity }) {} + ` + ); }); diff --git a/packages/babel-plugin-minify-mangle-names/__tests__/mangle-names-test.js b/packages/babel-plugin-minify-mangle-names/__tests__/mangle-names-test.js index 2d9c16a07..59adfa805 100644 --- a/packages/babel-plugin-minify-mangle-names/__tests__/mangle-names-test.js +++ b/packages/babel-plugin-minify-mangle-names/__tests__/mangle-names-test.js @@ -1,579 +1,547 @@ jest.autoMockOff(); -const traverse = require("babel-traverse").default; const babel = require("babel-core"); const unpad = require("../../../utils/unpad"); - -function transform(code, options = {}, sourceType = "script") { - return babel.transform(code, { - sourceType, - plugins: [[require("../src/index"), options]] - }).code; -} - -function transformWithSimplify(code, options = {}, sourceType = "script") { - return babel.transform(code, { - sourceType, - plugins: [ - require("../../babel-plugin-minify-simplify/src/index"), - [require("../src/index"), options] - ] - }).code; -} +const traverse = require("babel-traverse").default; +const mangler = require("../src/index"); +const thePlugin = require("../../../utils/test-transform")(mangler); describe("mangle-names", () => { - it("should not mangle names in the global namespace", () => { - const source = unpad(` - var Foo = 1; - `); - const expected = unpad(` - var Foo = 1; - `); - - expect(transform(source)).toBe(expected); - }); - - it("should mangle names", () => { - const source = unpad(` - function foo() { - var xxx = 1; - if (xxx) { - console.log(xxx); - } - } - `); - const expected = unpad(` - function foo() { - var a = 1; - if (a) { - console.log(a); - } - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should handle name collisions", () => { - const source = unpad(` - function foo() { - var x = 2; - var xxx = 1; - if (xxx) { - console.log(xxx + x); - } - } - `); - const expected = unpad(` - function foo() { - var a = 2; - var b = 1; - if (b) { - console.log(b + a); - } - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should be fine with shadowing", () => { - const source = unpad(` + thePlugin( + "should not mangle names in the global namespace", + ` + var Foo = 1; + ` + ); + + thePlugin( + "should mangle names", + ` + function foo() { + var xxx = 1; + if (xxx) { + console.log(xxx); + } + } + `, + ` + function foo() { var a = 1; - function foo() { - var xxx = 1; - if (xxx) { - console.log(xxx); - } - } - `); - const expected = unpad(` + if (a) { + console.log(a); + } + } + ` + ); + + thePlugin( + "should handle name collisions", + ` + function foo() { + var x = 2; + var xxx = 1; + if (xxx) { + console.log(xxx + x); + } + } + `, + ` + function foo() { + var a = 2; + var b = 1; + if (b) { + console.log(b + a); + } + } + ` + ); + + thePlugin( + "should be fine with shadowing", + ` + var a = 1; + function foo() { + var xxx = 1; + if (xxx) { + console.log(xxx); + } + } + `, + ` + var a = 1; + function foo() { var a = 1; - function foo() { - var a = 1; - if (a) { - console.log(a); - } - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not shadow outer references", () => { - const source = unpad(` - function bar() { - function foo(a, b, c) { - lol(a,b,c); - } - function lol() {} - } - `); - const expected = unpad(` - function bar() { - function a(e, a, b) { - d(e, a, b); - } - function d() {} - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should mangle args", () => { - const source = unpad(` - function foo(xxx) { - if (xxx) { - console.log(xxx); - } - } - `); - const expected = unpad(` - function foo(a) { - if (a) { - console.log(a); - } - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should ignore labels", () => { - const source = unpad(` - function foo() { - meh: for (;;) { - continue meh; - } - } - `); - - const expected = unpad(` - function foo() { - meh: for (;;) { - continue meh; - } - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not have labels conflicting with bindings", () => { - const source = unpad(` - function foo() { - meh: for (;;) { - var meh; - break meh; - } - } - `); - - const expected = unpad(` - function foo() { - meh: for (;;) { - var a; - break meh; - } - } - `); - - expect(transform(source)).toBe(expected); - }); - - // https://phabricator.babeljs.io/T6957 - it("labels should not shadow bindings", () => { - const source = unpad(` - function foo() { + if (a) { + console.log(a); + } + } + ` + ); + + thePlugin( + "should not shadow outer references", + ` + function bar() { + function foo(a, b, c) { + lol(a,b,c); + } + function lol() {} + } + `, + ` + function bar() { + function a(e, a, b) { + d(e, a, b); + } + function d() {} + } + ` + ); + + thePlugin( + "should mangle args", + ` + function foo(xxx) { + if (xxx) { + console.log(xxx); + } + } + `, + ` + function foo(a) { + if (a) { + console.log(a); + } + } + ` + ); + + thePlugin( + "should ignore labels", + ` + function foo() { + meh: for (;;) { + continue meh; + } + } + `, + ` + function foo() { + meh: for (;;) { + continue meh; + } + } + ` + ); + + thePlugin( + "should not have labels conflicting with bindings", + ` + function foo() { + meh: for (;;) { var meh; - meh: for (;;) { - break meh; - } - return meh; + break meh; } - `); - - const expected = unpad(` - function foo() { + } + `, + ` + function foo() { + meh: for (;;) { var a; - meh: for (;;) { - break meh; - } - return a; - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("labels should not shadow bindings 2", () => { - const source = unpad(` - function f(a) { - try { - a: { - console.log(a); - } - } catch ($a) { } + break meh; } - `); - const expected = unpad(` - function f(b) { - try { - a: { - console.log(b); - } - } catch (a) {} - } - `); - expect(transform(source)).toBe(expected); - }); + } + ` + ); - it("should be order independent", () => { - const source = unpad(` - function foo() { - function bar(aaa, bbb, ccc) { - baz(aaa, bbb, ccc); - } - function baz() { - var baz = who(); - baz.bam(); + // https://phabricator.babeljs.io/T6957 + thePlugin( + "labels should not shadow bindings", + ` + function foo() { + var meh; + meh: for (;;) { + break meh; + } + return meh; + } + `, + ` + function foo() { + var a; + meh: for (;;) { + break meh; + } + return a; + } + ` + ); + + thePlugin( + "labels should not shadow bindings 2", + ` + function f(a) { + try { + a: { + console.log(a); } - bar(); + } catch ($a) { } + } + `, + ` + function f(b) { + try { + a: { + console.log(b); + } + } catch (a) {} + } + ` + ); + + thePlugin( + "should be order independent", + ` + function foo() { + function bar(aaa, bbb, ccc) { + baz(aaa, bbb, ccc); + } + function baz() { + var baz = who(); + baz.bam(); + } + bar(); + } + `, + ` + function foo() { + function a(a, c, d) { + b(a, c, d); + } + function b() { + var a = who(); + a.bam(); } - `); - - const expected = unpad(` - function foo() { - function a(a, c, d) { - b(a, c, d); - } - function b() { - var a = who(); - a.bam(); - } + a(); + } + ` + ); + + thePlugin( + "should be order independent 2", + ` + function foo() { + (function bar() { + bar(); + return function() { + var bar = wow(); + bar.woo(); + }; + })(); + } + `, + ` + function foo() { + (function a() { a(); + return function () { + var a = wow(); + a.woo(); + }; + })(); + } + ` + ); + + thePlugin( + "should handle only thunk in function scopes", + ` + function foo() { + function xx(bar, baz) { + if (1) { + yy(bar, baz); + } + } + function yy(){} + } + `, + ` + function foo() { + function a(a, c) { + if (1) { + b(a, c); + } + } + function b() {} + } + ` + ); + + thePlugin( + "should be fine with shadowing 2", + ` + function foo() { + function xx(bar, baz) { + return function(boo, foo) { + bar(boo, foo); + }; } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should be order independent 2", () => { - const source = unpad(` - function foo() { - (function bar() { - bar(); - return function() { - var bar = wow(); - bar.woo(); - }; - })(); - } - `); - - const expected = unpad(` - function foo() { - (function a() { - a(); - return function () { - var a = wow(); - a.woo(); - }; - })(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should handle only thunk in function scopes", () => { - const source = unpad(` - function foo() { - function xx(bar, baz) { - if (1) { - yy(bar, baz); - } - } - function yy(){} - } - `); - const expected = unpad(` - function foo() { - function a(a, c) { - if (1) { - b(a, c); - } - } - function b() {} - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should be fine with shadowing 2", () => { - const source = unpad(` - function foo() { - function xx(bar, baz) { - return function(boo, foo) { - bar(boo, foo); - }; - } - function yy(){} - } - `); - const expected = unpad(` - function foo() { - function a(a, b) { - return function (b, c) { - a(b, c); - }; - } - function b() {} - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not be confused by scopes", () => { - const source = unpad(` - function foo() { - function bar() { - var baz; - if (baz) { - bam(); - } - } - function bam() {} - } - `); - const expected = unpad(` - function foo() { - function a() { - var a; - if (a) { - b(); - } - } - function b() {} - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not be confused by scopes (closures)", () => { - const source = unpad(` - function foo() { - function bar(baz) { - return function() { - bam(); - }; - } - function bam() {} - } - `); - const expected = unpad(` - function foo() { - function a(a) { - return function () { - b(); - }; - } - function b() {} + function yy(){} + } + `, + ` + function foo() { + function a(a, b) { + return function (b, c) { + a(b, c); + }; } - `); - - expect(transform(source)).toBe(expected); - }); + function b() {} + } + ` + ); - it("should handle recursion", () => { - const source = unpad(` + thePlugin( + "should not be confused by scopes", + ` + function foo() { function bar() { - function foo(a, b, c) { - foo(a,b,c); + var baz; + if (baz) { + bam(); } } - `); - const expected = unpad(` - function bar() { - function d(e, a, b) { - d(e, a, b); + function bam() {} + } + `, + ` + function foo() { + function a() { + var a; + if (a) { + b(); } } - `); - - expect(transform(source)).toBe(expected); - }); + function b() {} + } + ` + ); - it("should handle global name conflict", () => { - const source = unpad(` - function e() { - function foo() { - b = bar(); - } - function bar() {} + thePlugin( + "should not be confused by scopes (closures)", + ` + function foo() { + function bar(baz) { + return function() { + bam(); + }; } - `); - const expected = unpad(` - function e() { - function a() { - b = c(); - } - function c() {} + function bam() {} + } + `, + ` + function foo() { + function a(a) { + return function () { + b(); + }; } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should handle global name", () => { - const source = unpad(` + function b() {} + } + ` + ); + + thePlugin( + "should handle recursion", + ` + function bar() { + function foo(a, b, c) { + foo(a,b,c); + } + } + `, + ` + function bar() { + function d(e, a, b) { + d(e, a, b); + } + } + ` + ); + + thePlugin( + "should handle global name conflict", + ` + function e() { function foo() { - var bar = 1; - var baz = 2; + b = bar(); } - `); - - const expected = unpad(` + function bar() {} + } + `, + ` + function e() { function a() { - var bar = 1; - var a = 2; - } - `); - expect( - transform(source, { - blacklist: { foo: false, bar: true }, - topLevel: true - }) - ).toBe(expected); - }); - - it("should handle deeply nested paths with no bindings", () => { - const source = unpad(` - function xoo() { - function foo(zz, xx, yy) { - function bar(zip, zap, zop) { - return function(bar) { - zap(); - return function() { - zip(); - } + b = c(); + } + function c() {} + } + ` + ); + + thePlugin( + "should handle global name", + ` + function foo() { + var bar = 1; + var baz = 2; + } + `, + ` + function a() { + var bar = 1; + var a = 2; + } + `, + { + plugins: [ + [ + mangler, + { + blacklist: { foo: false, bar: true }, + topLevel: true + } + ] + ] + } + ); + + thePlugin( + "should handle deeply nested paths with no bindings", + ` + function xoo() { + function foo(zz, xx, yy) { + function bar(zip, zap, zop) { + return function(bar) { + zap(); + return function() { + zip(); } } } } - `); - const expected = unpad(` - function xoo() { - function a(a, b, c) { - function d(a, b, c) { - return function (c) { - b(); - return function () { - a(); - }; + } + `, + ` + function xoo() { + function a(a, b, c) { + function d(a, b, c) { + return function (c) { + b(); + return function () { + a(); }; - } - } - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should handle try/catch", () => { - const source = unpad(` - function xoo() { - var e; - try {} catch (e) { - + }; } } - `); - const expected = unpad(` - function xoo() { - var a; - try {} catch (a) {} - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should not mangle vars in scope with eval", () => { - const source = unpad(` - function foo() { - var inScopeOuter = 1; + } + ` + ); + + thePlugin( + "should handle try/catch", + ` + function xoo() { + var e; + try {} catch (e) { + + } + } + `, + ` + function xoo() { + var a; + try {} catch (a) {} + } + ` + ); + + thePlugin( + "should not mangle vars in scope with eval", + ` + function foo() { + var inScopeOuter = 1; + (function () { + var inScopeInner = 2; + eval("inScopeInner + inScopeOuter"); (function () { - var inScopeInner = 2; - eval("inScopeInner + inScopeOuter"); - (function () { - var outOfScope = 1; - })(); + var outOfScope = 1; })(); - } - `); - const expected = unpad(` - function foo() { - var inScopeOuter = 1; + })(); + } + `, + ` + function foo() { + var inScopeOuter = 1; + (function () { + var inScopeInner = 2; + eval("inScopeInner + inScopeOuter"); (function () { - var inScopeInner = 2; - eval("inScopeInner + inScopeOuter"); - (function () { - var a = 1; - })(); + var a = 1; })(); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should mangle names with local eval bindings", () => { - const source = unpad(` - function eval() {} - function foo() { - var bar = 1; - eval('...'); - } - `); - const expected = unpad(` - function eval() {} - function foo() { - var a = 1; - eval('...'); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should mangle names with option eval = true", () => { - const source = unpad(` - function foo() { - var inScopeOuter = 1; + })(); + } + ` + ); + + thePlugin( + "should mangle names with local eval bindings", + ` + function eval() {} + function foo() { + var bar = 1; + eval('...'); + } + `, + ` + function eval() {} + function foo() { + var a = 1; + eval('...'); + } + ` + ); + + thePlugin( + "should mangle names with option eval = true", + ` + function foo() { + var inScopeOuter = 1; + (function () { + var inScopeInner = 2; + eval("..."); (function () { - var inScopeInner = 2; - eval("..."); - (function () { - var outOfScope = 1; - })(); + var outOfScope = 1; })(); - } - `); - const expected = unpad(` - function foo() { - var a = 1; + })(); + } + `, + ` + function foo() { + var a = 1; + (function () { + var a = 2; + eval("..."); (function () { - var a = 2; - eval("..."); - (function () { - var a = 1; - })(); + var a = 1; })(); - } - `); - expect(transform(source, { eval: true })).toBe(expected); - }); + })(); + } + `, + { + plugins: [[mangler, { eval: true }]] + } + ); it("should integrate with block scoping plugin", () => { const srcTxt = unpad(` @@ -652,77 +620,73 @@ describe("mangle-names", () => { function a() { if (smth) { var a = blah(); - a(); - } - b(); - } - function b() {} - module.exports = { bar: a }; - })(); - `); - - expect(actual).toBe(expected); - }); - - it("should keep mangled named consistent across scopes when defined later on", () => { - const source = unpad(` - (function() { - function foo() { - { - var baz = true; - - { - bar(); - } - } - } - - function bar() {} - }()); - `); - - const expected = unpad(` - (function () { - function a() { - { - var a = true; - - { - b(); - } + a(); } + b(); } - function b() {} + module.exports = { bar: a }; })(); `); - expect(transform(source)).toBe(expected); + expect(actual).toBe(expected); }); - it("should correctly mangle in nested loops", () => { - const source = unpad(` - (function () { - for (let x in foo) { - for (let y in foo[x]) { - alert(foo[x][y]); + thePlugin( + "should keep mangled named consistent across scopes when defined later on", + ` + (function() { + function foo() { + { + var baz = true; + + { + bar(); } } - })(); - `); + } - const expected = unpad(` - (function () { - for (let a in foo) { - for (let b in foo[a]) { - alert(foo[a][b]); + function bar() {} + }()); + `, + ` + (function () { + function a() { + { + var a = true; + + { + b(); } } - })(); - `); + } - expect(transform(source)).toBe(expected); - }); + function b() {} + })(); + ` + ); + + thePlugin( + "should correctly mangle in nested loops", + ` + (function () { + for (let x in foo) { + for (let y in foo[x]) { + alert(foo[x][y]); + } + } + })(); + `, + ` + (function () { + for (let a in foo) { + for (let b in foo[a]) { + alert(foo[a][b]); + } + } + })(); + ` + ); // #issue55, #issue57 it("should correctly mangle function declarations in different order", () => { @@ -767,520 +731,552 @@ describe("mangle-names", () => { expect(actual).toBe(expected); }); - it("should NOT mangle functions when keepFnName is true", () => { - const source = unpad(` - (function() { - var foo = function foo() { - foo(); - } - function bar() { - foo(); - } - bar(); - var baz = foo; - baz(); - })(); - `); - const expected = unpad(` - (function () { - var a = function foo() { - foo(); - }; - function bar() { - a(); - } - bar(); - var b = a; - b(); - })(); - `); - expect(transform(source, { keepFnName: true })).toBe(expected); - }); - - it("should NOT mangle classes when keepClassName is true", () => { - const source = unpad(` - (function() { - class Foo {} - const Bar = class Bar extends Foo {} - var foo = class Baz {} - function bar() { - new foo(); - } - bar(); - })(); - `); - const expected = unpad(` - (function () { - class Foo {} - const b = class Bar extends Foo {}; - var c = class Baz {}; - function a() { - new c(); - } - a(); - })(); - `); - expect(transform(source, { keepClassName: true })).toBe(expected); - }); - - it("should mangle variable re-declaration / K violations", () => { - const source = unpad(` - !function () { - var foo = 1; - foo++; - var foo = 2; - foo++; + thePlugin( + "should NOT mangle functions when keepFnName is true", + ` + (function() { + var foo = function foo() { + foo(); } - `); - const expected = unpad(` - !function () { - var a = 1; - a++; - var a = 2; - a++; - }; - `); - expect(transform(source)).toBe(expected); - }); - - it("should handle K violations - 2", () => { - const source = unpad(` - !function () { - var bar = 1; - bar--; - var bar = 10; - foo(bar) - function foo() { - var foo = 10; - foo++; - var foo = 20; - foo(foo); - } + function bar() { + foo(); } - `); - const expected = unpad(` - !function () { - var b = 1; - b--; - var b = 10; - a(b); - function a() { - var a = 10; - a++; - var a = 20; - a(a); - } + bar(); + var baz = foo; + baz(); + })(); + `, + ` + (function () { + var a = function foo() { + foo(); }; - `); - expect(transform(source)).toBe(expected); - }); - - it("should work with redeclarations", () => { - const source = unpad(` - (function () { - var x = y; - x = z; - x; - })(); - `); - const expected = unpad(` - (function () { - var a = y; - a = z; - a; - })(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should reuse removed vars", () => { - const source = unpad(` + function bar() { + a(); + } + bar(); + var b = a; + b(); + })(); + `, + { + plugins: [[mangler, { keepFnName: true }]] + } + ); + + thePlugin( + "should NOT mangle classes when keepClassName is true", + ` + (function() { + class Foo {} + const Bar = class Bar extends Foo {} + var foo = class Baz {} + function bar() { + new foo(); + } + bar(); + })(); + `, + ` + (function () { + class Foo {} + const b = class Bar extends Foo {}; + var c = class Baz {}; + function a() { + new c(); + } + a(); + })(); + `, + { + plugins: [[mangler, { keepClassName: true }]] + } + ); + + thePlugin( + "should mangle variable re-declaration / K violations", + ` + !function () { + var foo = 1; + foo++; + var foo = 2; + foo++; + } + `, + ` + !function () { + var a = 1; + a++; + var a = 2; + a++; + }; + ` + ); + + thePlugin( + "should handle K violations - 2", + ` + !function () { + var bar = 1; + bar--; + var bar = 10; + foo(bar) + function foo() { + var foo = 10; + foo++; + var foo = 20; + foo(foo); + } + } + `, + ` + !function () { + var b = 1; + b--; + var b = 10; + a(b); + function a() { + var a = 10; + a++; + var a = 20; + a(a); + } + }; + ` + ); + + thePlugin( + "should work with redeclarations", + ` + (function () { + var x = y; + x = z; + x; + })(); + `, + ` + (function () { + var a = y; + a = z; + a; + })(); + ` + ); + + thePlugin( + "should reuse removed vars", + ` + function Foo() { + var a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; + var A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z; + var $, _; + a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; + A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z; + $, _; function Foo() { - var a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; + var a, b, c, d, e, f, g, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; var A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z; var $, _; - a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; + a, b, c, d, e, f, g, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z; $, _; function Foo() { - var a, b, c, d, e, f, g, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; + var a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; var A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z; var $, _; - a, b, c, d, e, f, g, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; + a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z; $, _; - function Foo() { - var a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; - var A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z; - var $, _; - a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; - A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z; - $, _; - } - Foo(); } Foo(); - } - `); - const expected = unpad(` - function Foo() { - var ba, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y; - var z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; - var Z, $; - ba, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y; - z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; - Z, $; - function aa() { - var aa, a, b, c, d, e, f, g, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y; - var z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; - var Z, $; - aa, a, b, c, d, e, f, g, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y; - z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; - Z, $; - function h() { - var aa, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y; - var z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; - var Z, $; - aa, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y; - z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; - Z, $; - } - h(); - } - aa(); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should mangle both referenced and binding identifiers with K violations", () => { - const source = unpad(` - (function () { - var foo = bar, - foo = baz; - foo; - })(); - `); - const expected = unpad(` - (function () { - var a = bar, - a = baz; - a; - })(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should handle export declarations", () => { - const source = unpad(` - const foo = 1; - export { foo }; - export const bar = 2; - export function baz(bar, foo) { - bar(); - foo(); - }; - export default function (bar, baz) { - bar(); - baz(); - } - `); - const expected = unpad(` - const foo = 1; - export { foo }; - export const bar = 2; - export function baz(a, b) { - a(); - b(); - }; - export default function (a, b) { - a(); - b(); - } - `); - expect(transform(source, {}, "module")).toBe(expected); - }); - - it("should find global scope properly", () => { - const source = unpad(` - class A {} - class B extends A {} - (function () { - class C { - constructor() { - new A(); - new B(); - C; - } - } - })(); - `); - const expected = unpad(` - class A {} - class B extends A {} - (function () { - class a { - constructor() { - new A(); - new B(); - a; - } - } - })(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should mangle classes properly", () => { - const source = unpad(` - class A {} - class B {} - new A(); - new B(); - function a() { - class A {} - class B {} - new A(); - new B(); - } - `); - const expected = unpad(` - class A {} - class B {} - new A(); - new B(); - function a() { - class a {} - class b {} - new a(); - new b(); - } - `); - expect(transform(source)).toBe(expected); - }); - - // https://github.com/babel/babili/issues/138 - it("should handle class exports in modules - issue#138", () => { - const source = unpad(` - export class App extends Object {}; - `); - const expected = source; - expect(transform(source, {}, "module")).toBe(expected); - }); - - it("should not mangle the name arguments", () => { - const source = unpad(` - (function () { - var arguments = void 0; - (function () { - console.log(arguments); - })("argument"); - })(); - `); - const expected = source; - expect(transform(source)).toBe(expected); - }); - - it("should mangle topLevel when topLevel option is true", () => { - const source = unpad(` - function foo() { - if (FOO_ENV === "production") { - HELLO_WORLD.call(); - } - } - const FOO_ENV = "production"; - var HELLO_WORLD = function bar() { - new AbstractClass({ - [FOO_ENV]: "foo", - a: foo(HELLO_WORLD) - }); - }; - class AbstractClass {} - foo(); - `); - - const expected = unpad(` - function a() { - if (b === "production") { - c.call(); - } - } - const b = "production"; - var c = function e() { - new d({ - [b]: "foo", - a: a(c) - }); - }; - class d {} - a(); - `); - - expect(transform(source, { topLevel: true })).toBe(expected); - }); - - it("should fix #326, #369 - destructuring", () => { - const source = unpad(` - // issue#326 - function a() { - let foo, bar, baz; - ({foo, bar, baz} = {}); - return {foo, bar, baz}; - } - // issue#369 - function decodeMessage(message){ - let namespace; - let name; - let value = null; - - [, namespace, name, value] = message.split(',') || []; - console.log(name); - } - `); - const expected = unpad(` - // issue#326 - function a() { - let a, b, c; - ({ foo: a, bar: b, baz: c } = {}); - return { foo: a, bar: b, baz: c }; - } - // issue#369 - function decodeMessage(a) { - let b; - let c; - let d = null; - - [, b, c, d] = a.split(',') || []; - console.log(c); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should rename binding.identifier - issue#411", () => { - const source = unpad(` - !function () { - function e(e) { - foo(e); - } - return function () { - return e(); - }; - }(); - `); - const expected = unpad(` - !function () { - function a(a) { - foo(a); - } - return function () { - return a(); - }; - }(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should fix issue#365 - classDeclaration with unsafe parent scope", () => { - const source = unpad(` - function foo() { - eval(""); - class A {} - class B {} - } - `); - expect(transform(source)).toBe(source); - }); - - it("should fix classDeclaration with unsafe program scope", () => { - const source = unpad(` + } + Foo(); + } + `, + ` + function Foo() { + var ba, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y; + var z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; + var Z, $; + ba, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y; + z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; + Z, $; + function aa() { + var aa, a, b, c, d, e, f, g, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y; + var z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; + var Z, $; + aa, a, b, c, d, e, f, g, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y; + z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; + Z, $; + function h() { + var aa, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y; + var z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; + var Z, $; + aa, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y; + z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y; + Z, $; + } + h(); + } + aa(); + } + ` + ); + + thePlugin( + "should mangle both referenced and binding identifiers with K violations", + ` + (function () { + var foo = bar, + foo = baz; + foo; + })(); + `, + ` + (function () { + var a = bar, + a = baz; + a; + })(); + ` + ); + + thePlugin( + "should handle export declarations", + ` + const foo = 1; + export { foo }; + export const bar = 2; + export function baz(bar, foo) { + bar(); + foo(); + }; + export default function (bar, baz) { + bar(); + baz(); + } + `, + ` + const foo = 1; + export { foo }; + export const bar = 2; + export function baz(a, b) { + a(); + b(); + }; + export default function (a, b) { + a(); + b(); + } + `, + { + sourceType: "module" + } + ); + + thePlugin( + "should find global scope properly", + ` + class A {} + class B extends A {} + (function () { + class C { + constructor() { + new A(); + new B(); + C; + } + } + })(); + `, + ` + class A {} + class B extends A {} + (function () { + class a { + constructor() { + new A(); + new B(); + a; + } + } + })(); + ` + ); + + thePlugin( + "should mangle classes properly", + ` + class A {} + class B {} + new A(); + new B(); + function a() { class A {} class B {} - eval(""); - `); - expect(transform(source, { topLevel: true })).toBe(source); - }); + new A(); + new B(); + } + `, + ` + class A {} + class B {} + new A(); + new B(); + function a() { + class a {} + class b {} + new a(); + new b(); + } + ` + ); - it("should handle constant violations across multiple blocks", () => { - const source = unpad(` - function foo() { + // https://github.com/babel/babili/issues/138 + thePlugin( + "should handle class exports in modules - issue#138", + ` + export class App extends Object {}; + `, + { + sourceType: "module" + } + ); + + thePlugin( + "should not mangle the name arguments", + ` + (function () { + var arguments = void 0; + (function () { + console.log(arguments); + })("argument"); + })(); + ` + ); + + thePlugin( + "should mangle topLevel when topLevel option is true", + ` + function foo() { + if (FOO_ENV === "production") { + HELLO_WORLD.call(); + } + } + const FOO_ENV = "production"; + var HELLO_WORLD = function bar() { + new AbstractClass({ + [FOO_ENV]: "foo", + a: foo(HELLO_WORLD) + }); + }; + class AbstractClass {} + foo(); + `, + ` + function a() { + if (b === "production") { + c.call(); + } + } + const b = "production"; + var c = function e() { + new d({ + [b]: "foo", + a: a(c) + }); + }; + class d {} + a(); + `, + { + plugins: [[mangler, { topLevel: true }]] + } + ); + + thePlugin( + "should fix #326, #369 - destructuring", + ` + // issue#326 + function a() { + let foo, bar, baz; + ({foo, bar, baz} = {}); + return {foo, bar, baz}; + } + // issue#369 + function decodeMessage(message){ + let namespace; + let name; + let value = null; + + [, namespace, name, value] = message.split(',') || []; + console.log(name); + } + `, + ` + // issue#326 + function a() { + let a, b, c; + ({ foo: a, bar: b, baz: c } = {}); + return { foo: a, bar: b, baz: c }; + } + // issue#369 + function decodeMessage(a) { + let b; + let c; + let d = null; + + [, b, c, d] = a.split(',') || []; + console.log(c); + } + ` + ); + + thePlugin( + "should rename binding.identifier - issue#411", + ` + !function () { + function e(e) { + foo(e); + } + return function () { + return e(); + }; + }(); + `, + ` + !function () { + function a(a) { + foo(a); + } + return function () { + return a(); + }; + }(); + ` + ); + + thePlugin( + "should fix issue#365 - classDeclaration with unsafe parent scope", + ` + function foo() { + eval(""); + class A {} + class B {} + } + ` + ); + + thePlugin( + "should fix classDeclaration with unsafe program scope", + ` + class A {} + class B {} + eval(""); + `, + { + plugins: [[mangler, { topLevel: true }]] + } + ); + + thePlugin( + "should handle constant violations across multiple blocks", + ` + function foo() { + var x;x;x; + { var x;x;x; - { + function y() { var x;x;x; - function y() { + { var x;x;x; - { - var x;x;x; - } } } } - `); - const expected = unpad(` - function foo() { + } + `, + ` + function foo() { + var a;a;a; + { var a;a;a; - { + function b() { var a;a;a; - function b() { + { var a;a;a; - { - var a;a;a; - } } } } - `); - expect(transform(source)).toBe(expected); - }); - - it("should work with if_return optimization changing fn scope", () => { - const source = unpad(` - function foo() { - if (x) - return; - function bar() {} - bar(a); - } - `); - const expected = unpad(` - function foo() { - function b() {} - x || b(a); - } - `); - expect(transformWithSimplify(source)).toBe(expected); - }); - - it("should not mangle named exports - 1", () => { - const source = unpad(` - export const Foo = foo; - `); - expect(transform(source, { topLevel: true }, "module")).toBe(source); - }); - - it("should not mangle named exports - 2", () => { - const source = unpad(` - const Foo = a; - export {Foo}; - `); - const expected = unpad(` - const b = a; - export { b as Foo }; - `); - expect(transform(source, { topLevel: true }, "module")).toBe(expected); - }); - - it("should not mangle named exports - 3", () => { - const source = unpad(` - const Foo = a; - export {Foo as Bar}; - `); - const expected = unpad(` - const b = a; - export { b as Bar }; - `); - expect(transform(source, { topLevel: true }, "module")).toBe(expected); - }); + } + ` + ); + + thePlugin( + "should work with if_return optimization changing fn scope", + ` + function foo() { + if (x) + return; + function bar() {} + bar(a); + } + `, + ` + function foo() { + function b() {} + x || b(a); + } + `, + { + plugins: [ + require("../../babel-plugin-minify-simplify/src/index"), + mangler + ] + } + ); + + thePlugin( + "should not mangle named exports - 1", + ` + export const Foo = foo; + `, + { + sourceType: "module", + plugins: [[mangler, { topLevel: true }]] + } + ); + + thePlugin( + "should not mangle named exports - 2", + ` + const Foo = a; + export {Foo}; + `, + ` + const b = a; + export { b as Foo }; + `, + { + sourceType: "module", + plugins: [[mangler, { topLevel: true }]] + } + ); + + thePlugin( + "should not mangle named exports - 3", + ` + const Foo = a; + export {Foo as Bar}; + `, + ` + const b = a; + export { b as Bar }; + `, + { + sourceType: "module", + plugins: [[mangler, { topLevel: true }]] + } + ); // Safari raises a syntax error for a `let` or `const` declaration in a `for` // loop initialization that shadows a parent function's parameter. @@ -1288,8 +1284,9 @@ describe("mangle-names", () => { // https://bugs.webkit.org/show_bug.cgi?id=171041 // https://trac.webkit.org/changeset/217200/webkit/trunk/Source describe("Safari for loop lexical scope workaround", () => { - it("should permit shadowing in top-level for loops", () => { - const source = unpad(` + thePlugin( + "should permit shadowing in top-level for loops", + ` var a; for (a = 0;;); @@ -1313,8 +1310,8 @@ describe("mangle-names", () => { for (;; () => { let a = 1; }); - `); - const expected = unpad(` + `, + ` var a; for (a = 0;;); @@ -1338,71 +1335,14 @@ describe("mangle-names", () => { for (;; () => { let b = 1; }); - `); - expect(transform(source)).toBe(expected); - }); - - it("should permit shadowing in nested for loops", () => { - const source = unpad(` - function a(a) { - { - for (a = 0;;); - for (a of x); - for (x of a); - for (a in x); - for (x in a); - for (;; a++); - for (;; a = 1); - - for (let a;;); - for (let a of x); - for (const a of x); - for (let a in x); - for (const a in x); - for (let [a, b] of x); - for (const [a, b] of x); - for (let [a, b] in x); - for (const [a, b] in x); - for (let { c: { b: { a } } } = x;;); - for (;; () => { - let a = 1; - }); - } - } - `); - const expected = unpad(` - function a(b) { - { - for (b = 0;;); - for (b of x); - for (x of b); - for (b in x); - for (x in b); - for (;; b++); - for (;; b = 1); - - for (let b;;); - for (let b of x); - for (const b of x); - for (let b in x); - for (const b in x); - for (let [c, a] of x); - for (const [c, a] of x); - for (let [c, a] in x); - for (const [c, a] in x); - for (let { c: { b: { a: b } } } = x;;); - for (;; () => { - let b = 1; - }); - } - } - `); - expect(transform(source)).toBe(expected); - }); + ` + ); - it("should not shadow params in function declaration top-level for loops", () => { - const source = unpad(` - function a(a) { + thePlugin( + "should permit shadowing in nested for loops", + ` + function a(a) { + { for (a = 0;;); for (a of x); for (x of a); @@ -1411,23 +1351,25 @@ describe("mangle-names", () => { for (;; a++); for (;; a = 1); - for (let b;;); - for (let b of x); - for (const b of x); - for (let b in x); - for (const b in x); - for (let [b, c] of x); - for (const [b, c] of x); - for (let [b, c] in x); - for (const [b, c] in x); + for (let a;;); + for (let a of x); + for (const a of x); + for (let a in x); + for (const a in x); + for (let [a, b] of x); + for (const [a, b] of x); + for (let [a, b] in x); + for (const [a, b] in x); for (let { c: { b: { a } } } = x;;); for (;; () => { let a = 1; }); } - `); - const expected = unpad(` - function a(b) { + } + `, + ` + function a(b) { + { for (b = 0;;); for (b of x); for (x of b); @@ -1436,81 +1378,191 @@ describe("mangle-names", () => { for (;; b++); for (;; b = 1); - for (let a;;); - for (let a of x); - for (const a of x); - for (let a in x); - for (const a in x); - for (let [a, d] of x); - for (const [a, d] of x); - for (let [a, d] in x); - for (const [a, d] in x); - for (let { c: { b: { a: c } } } = x;;); - for (;; () => { - let b = 1; - }); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should not shadow params in function expression top-level for loops", () => { - const source = unpad(` - var a = function (a) { - for (a = 0;;); - for (a of x); - for (x of a); - for (a in x); - for (x in a); - for (;; a++); - for (;; a = 1); - for (let b;;); for (let b of x); for (const b of x); for (let b in x); for (const b in x); - for (let [b, c] of x); - for (const [b, c] of x); - for (let [b, c] in x); - for (const [b, c] in x); - for (let { c: { b: { a } } } = x;;); - for (;; () => { - let a = 1; - }); - }; - `); - const expected = unpad(` - var a = function (b) { - for (b = 0;;); - for (b of x); - for (x of b); - for (b in x); - for (x in b); - for (;; b++); - for (;; b = 1); - - for (let a;;); - for (let a of x); - for (const a of x); - for (let a in x); - for (const a in x); - for (let [a, d] of x); - for (const [a, d] of x); - for (let [a, d] in x); - for (const [a, d] in x); - for (let { c: { b: { a: c } } } = x;;); + for (let [c, a] of x); + for (const [c, a] of x); + for (let [c, a] in x); + for (const [c, a] in x); + for (let { c: { b: { a: b } } } = x;;); for (;; () => { let b = 1; }); - }; - `); - expect(transform(source)).toBe(expected); - }); + } + } + ` + ); + + thePlugin( + "should not shadow params in function declaration top-level for loops", + ` + function a(a) { + for (a = 0;;); + for (a of x); + for (x of a); + for (a in x); + for (x in a); + for (;; a++); + for (;; a = 1); + + for (let b;;); + for (let b of x); + for (const b of x); + for (let b in x); + for (const b in x); + for (let [b, c] of x); + for (const [b, c] of x); + for (let [b, c] in x); + for (const [b, c] in x); + for (let { c: { b: { a } } } = x;;); + for (;; () => { + let a = 1; + }); + } + `, + ` + function a(b) { + for (b = 0;;); + for (b of x); + for (x of b); + for (b in x); + for (x in b); + for (;; b++); + for (;; b = 1); + + for (let a;;); + for (let a of x); + for (const a of x); + for (let a in x); + for (const a in x); + for (let [a, d] of x); + for (const [a, d] of x); + for (let [a, d] in x); + for (const [a, d] in x); + for (let { c: { b: { a: c } } } = x;;); + for (;; () => { + let b = 1; + }); + } + ` + ); + + thePlugin( + "should not shadow params in function expression top-level for loops", + ` + var a = function (a) { + for (a = 0;;); + for (a of x); + for (x of a); + for (a in x); + for (x in a); + for (;; a++); + for (;; a = 1); + + for (let b;;); + for (let b of x); + for (const b of x); + for (let b in x); + for (const b in x); + for (let [b, c] of x); + for (const [b, c] of x); + for (let [b, c] in x); + for (const [b, c] in x); + for (let { c: { b: { a } } } = x;;); + for (;; () => { + let a = 1; + }); + }; + `, + ` + var a = function (b) { + for (b = 0;;); + for (b of x); + for (x of b); + for (b in x); + for (x in b); + for (;; b++); + for (;; b = 1); + + for (let a;;); + for (let a of x); + for (const a of x); + for (let a in x); + for (const a in x); + for (let [a, d] of x); + for (const [a, d] of x); + for (let [a, d] in x); + for (const [a, d] in x); + for (let { c: { b: { a: c } } } = x;;); + for (;; () => { + let b = 1; + }); + }; + ` + ); + + thePlugin( + "should not shadow params in arrow function top-level for loops", + ` + var a = (a) => { + for (a = 0;;); + for (a of x); + for (x of a); + for (a in x); + for (x in a); + for (;; a++); + for (;; a = 1); + + for (let b;;); + for (let b of x); + for (const b of x); + for (let b in x); + for (const b in x); + for (let [b, c] of x); + for (const [b, c] of x); + for (let [b, c] in x); + for (const [b, c] in x); + for (let { c: { b: { a } } } = x;;); + for (;; () => { + let a = 1; + }); + }; + `, + ` + var a = (b) => { + for (b = 0;;); + for (b of x); + for (x of b); + for (b in x); + for (x in b); + for (;; b++); + for (;; b = 1); - it("should not shadow params in arrow function top-level for loops", () => { - const source = unpad(` - var a = (a) => { + for (let a;;); + for (let a of x); + for (const a of x); + for (let a in x); + for (const a in x); + for (let [a, d] of x); + for (const [a, d] of x); + for (let [a, d] in x); + for (const [a, d] in x); + for (let { c: { b: { a: c } } } = x;;); + for (;; () => { + let b = 1; + }); + }; + ` + ); + + thePlugin( + "should not shadow params in class method top-level for loops", + ` + class a { + a(a) { for (a = 0;;); for (a of x); for (x of a); @@ -1532,10 +1584,12 @@ describe("mangle-names", () => { for (;; () => { let a = 1; }); - }; - `); - const expected = unpad(` - var a = (b) => { + } + } + `, + ` + class a { + a(b) { for (b = 0;;); for (b of x); for (x of b); @@ -1557,67 +1611,9 @@ describe("mangle-names", () => { for (;; () => { let b = 1; }); - }; - `); - expect(transform(source)).toBe(expected); - }); - - it("should not shadow params in class method top-level for loops", () => { - const source = unpad(` - class a { - a(a) { - for (a = 0;;); - for (a of x); - for (x of a); - for (a in x); - for (x in a); - for (;; a++); - for (;; a = 1); - - for (let b;;); - for (let b of x); - for (const b of x); - for (let b in x); - for (const b in x); - for (let [b, c] of x); - for (const [b, c] of x); - for (let [b, c] in x); - for (const [b, c] in x); - for (let { c: { b: { a } } } = x;;); - for (;; () => { - let a = 1; - }); - } } - `); - const expected = unpad(` - class a { - a(b) { - for (b = 0;;); - for (b of x); - for (x of b); - for (b in x); - for (x in b); - for (;; b++); - for (;; b = 1); - - for (let a;;); - for (let a of x); - for (const a of x); - for (let a in x); - for (const a in x); - for (let [a, d] of x); - for (const [a, d] of x); - for (let [a, d] in x); - for (const [a, d] in x); - for (let { c: { b: { a: c } } } = x;;); - for (;; () => { - let b = 1; - }); - } - } - `); - expect(transform(source)).toBe(expected); - }); + } + ` + ); }); }); diff --git a/packages/babel-plugin-minify-numeric-literals/__tests__/numeric-literals-test.js b/packages/babel-plugin-minify-numeric-literals/__tests__/numeric-literals-test.js index 1ff31927c..89e74e278 100644 --- a/packages/babel-plugin-minify-numeric-literals/__tests__/numeric-literals-test.js +++ b/packages/babel-plugin-minify-numeric-literals/__tests__/numeric-literals-test.js @@ -1,36 +1,33 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("numeric-literals", () => { - it("should shorten properly", () => { - let source = "[10, 100, 1000, 10000, -2, -30000];"; - let expected = "[10, 100, 1e3, 1e4, -2, -3e4];"; - - expect(transform(source)).toBe(expected); - - source = "[1e3, -1e4, 1e-5, 1.5e12, 1.23456, .1];"; - expected = "[1e3, -1e4, 1e-5, 1.5e12, 1.23456, .1];"; - - expect(transform(source)).toBe(expected); - - source = "[0x000001, 0o23420, 0b10011100010000];"; - expected = "[1, 1e4, 1e4];"; - - expect(transform(source)).toBe(expected); - - source = "[+0.000000000001, -0.00000000001];"; - // TODO: this seems to be specific to how Babel outputs number - // for some reason it adds + in the beginning - expected = "[+1e-12, -1e-11];"; - - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should shorten properly", + ` + [10, 100, 1000, 10000, -2, -30000]; + [1e3, -1e4, 1e-5, 1.5e12, 1.23456, .1]; + [0x000001, 0o23420, 0b10011100010000]; + `, + ` + [10, 100, 1e3, 1e4, -2, -3e4]; + [1e3, -1e4, 1e-5, 1.5e12, 1.23456, .1]; + [1, 1e4, 1e4]; + ` + ); + + // TODO: this seems to be specific to how Babel output numbers + // for some reason it adds + in the beginning + thePlugin.skip( + "should have correct signs", + ` + [+0.000000000001, -0.00000000001]; + `, + ` + [+1e-12, -1e-11]; + ` + ); }); diff --git a/packages/babel-plugin-minify-replace/__tests__/replace-test.js b/packages/babel-plugin-minify-replace/__tests__/replace-test.js index fbe45152a..bb4ab3ac9 100644 --- a/packages/babel-plugin-minify-replace/__tests__/replace-test.js +++ b/packages/babel-plugin-minify-replace/__tests__/replace-test.js @@ -1,162 +1,142 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const unpad = require("../../../utils/unpad"); - -function transform(code, replacements) { - return babel.transform(code, { - plugins: [[require("../src/index"), { replacements }]] - }).code; +const replacer = require("../src/index"); + +const theTester = require("../../../utils/test-transform")(replacer); +function thePlugin(name, source, expected, ...replacements) { + if (typeof expected === "object") { + replacements.unshift(expected); + expected = source; + } + theTester(name, source, expected, { + plugins: [[replacer, { replacements }]] + }); } +thePlugin.skip = theTester.skip(); describe("replace-plugin", () => { - it("should replace identifiers", () => { - const replacements = [ - { - identifierName: "__DEV__", - replacement: { - type: "numericLiteral", - value: 0 - } - } - ]; - - const source = unpad(` - if (__DEV__) { - foo(); - } - if (!__DEV__) { - foo(); - } - `); - - const expected = unpad(` - if (0) { - foo(); - } - if (!0) { - foo(); - } - `); - - expect(transform(source, replacements)).toBe(expected); - }); - - it("should only replace actual full identifiers", () => { - const replacements = [ - { - identifierName: "__DEV__", - replacement: { - type: "numericLiteral", - value: 0 - } + thePlugin( + "should replace identifiers", + ` + if (__DEV__) { + foo(); + } + if (!__DEV__) { + foo(); + } + `, + ` + if (0) { + foo(); + } + if (!0) { + foo(); + } + `, + { + identifierName: "__DEV__", + replacement: { + type: "numericLiteral", + value: 0 } - ]; - - const source = unpad(` - if (__DEV__) { - foo(); + } + ); + + thePlugin( + "should only replace actual full identifiers", + ` + if (__DEV__) { + foo(); + } + if (a.__DEV__) { + foo(); + } + `, + ` + if (0) { + foo(); + } + if (a.__DEV__) { + foo(); + } + `, + { + identifierName: "__DEV__", + replacement: { + type: "numericLiteral", + value: 0 } - if (a.__DEV__) { - foo(); + } + ); + + thePlugin( + "should replace with boolean", + ` + if (__DEV__) { + foo(); + } + `, + ` + if (true) { + foo(); + } + `, + { + identifierName: "__DEV__", + replacement: { + type: "booleanLiteral", + value: true } - `); - - const expected = unpad(` - if (0) { - foo(); + } + ); + + thePlugin( + "should replace member expressions", + ` + console.log('wat'); + (console.log)('wat'); + `, + ` + emptyFunction('wat'); + emptyFunction('wat'); + `, + { + identifierName: "console", + member: "log", + replacement: { + type: "identifier", + value: "emptyFunction" } - if (a.__DEV__) { - foo(); + } + ); + + thePlugin( + "should replace multiple member expressions", + ` + console.log('wat'); + (console.log)('wat'); + console.error('wat'); + `, + ` + emptyFunction('wat'); + emptyFunction('wat'); + emptyFunction('wat'); + `, + { + identifierName: "console", + member: "log", + replacement: { + type: "identifier", + value: "emptyFunction" } - `); - - expect(transform(source, replacements)).toBe(expected); - }); - - it("should replace with boolean", () => { - const replacements = [ - { - identifierName: "__DEV__", - replacement: { - type: "booleanLiteral", - value: true - } + }, + { + identifierName: "console", + member: "error", + replacement: { + type: "identifier", + value: "emptyFunction" } - ]; - - const source = unpad(` - if (__DEV__) { - foo(); - } - `); - - const expected = unpad(` - if (true) { - foo(); - } - `); - - expect(transform(source, replacements)).toBe(expected); - }); - - it("should replace member expressions", () => { - const replacements = [ - { - identifierName: "console", - member: "log", - replacement: { - type: "identifier", - value: "emptyFunction" - } - } - ]; - - const source = unpad(` - console.log('wat'); - (console.log)('wat'); - `); - - const expected = unpad(` - emptyFunction('wat'); - emptyFunction('wat'); - `); - - expect(transform(source, replacements)).toBe(expected); - }); - - it("should replace multiple member expressions", () => { - const replacements = [ - { - identifierName: "console", - member: "log", - replacement: { - type: "identifier", - value: "emptyFunction" - } - }, - { - identifierName: "console", - member: "error", - replacement: { - type: "identifier", - value: "emptyFunction" - } - } - ]; - - const source = unpad(` - console.log('wat'); - (console.log)('wat'); - console.error('wat'); - `); - - const expected = unpad(` - emptyFunction('wat'); - emptyFunction('wat'); - emptyFunction('wat'); - `); - - expect(transform(source, replacements)).toBe(expected); - }); + } + ); }); diff --git a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js index c8826cf7a..42b4f99e9 100644 --- a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js +++ b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js @@ -32,186 +32,180 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); const comparisonPlugin = require("../../babel-plugin-transform-simplify-comparison-operators/src"); -const unpad = require("../../../utils/unpad"); +const plugin = require("../src/index"); -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")(plugin); describe("simplify-plugin", () => { - it("should flip conditionals", () => { - const source = "!foo ? 'foo' : 'bar';"; - const expected = "foo ? 'bar' : 'foo';"; - expect(transform(source)).toBe(expected); - }); - - it("should turn for loop block to a single statement", () => { - const source = unpad(` - for (var x = 0; x < 10; x++) { - console.log(x); - } - `); - const expected = "for (var x = 0; x < 10; x++) console.log(x);"; + thePlugin( + "should flip conditionals", + ` + !foo ? 'foo' : 'bar'; + `, + ` + foo ? 'bar' : 'foo'; + ` + ); - expect(transform(source).trim()).toBe(expected); - }); + thePlugin( + "should turn for loop block to a single statement", + ` + for (var x = 0; x < 10; x++) { + console.log(x); + } + `, + ` + for (var x = 0; x < 10; x++) console.log(x); + ` + ); - it("should turn block statements to sequence expr", () => { - const source = unpad(` + thePlugin( + "should turn block statements to sequence expr", + ` for (var x = 0; x < 10; x++) { console.log(x); console.log(x); } - `); - const expected = - "for (var x = 0; x < 10; x++) console.log(x), console.log(x);"; + `, + ` + for (var x = 0; x < 10; x++) console.log(x), console.log(x); + ` + ); - expect(transform(source).trim()).toBe(expected); - }); + thePlugin( + "should the program into as much sequence exprs", + ` + x(); + y(); + for (var x = 0; x < 10; x++) { + var z = foo(); + console.log(z); + console.log(z); + } + a(); + b = 1; + `, + ` + x(), y(); - it("should the program into as much sequence exprs", () => { - const source = unpad(` - x(); - y(); - for (var x = 0; x < 10; x++) { - var z = foo(); - console.log(z); - console.log(z); - } - a(); - b = 1; - `); - const expected = unpad(` - x(), y(); + for (var x = 0; x < 10; x++) { + var z = foo(); + console.log(z), console.log(z); + } + a(), b = 1; + ` + ); - for (var x = 0; x < 10; x++) { - var z = foo(); - console.log(z), console.log(z); - } - a(), b = 1; - `); - expect(transform(source).trim()).toBe(expected); - }); - - it("should turn if to gaurded expression", () => { - const source = unpad(` - function foo() { - if (x) a(); - } - `); - const expected = unpad(` - function foo() { - x && a(); - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should turn if statement to conditional", () => { - const source = unpad(` - function foo() { - if (x) a(); - else b(); - } - `); - const expected = unpad(` - function foo() { - x ? a() : b(); - } - `); - - expect(transform(source).trim()).toBe(expected); - }); - - it("should turn this into a conditional", () => { - const source = unpad(` - function foo(a) { - if (a && a.b != null) { - if ((a.c--) === 1) { - delete a.c; - } - return a.b; - } - return bar(a); - } - `); - const expected = unpad(` - function foo(a) { - return a && a.b != null ? (a.c-- === 1 && delete a.c, a.b) : bar(a); - } - `); + thePlugin( + "should turn if to gaurded expression", + ` + function foo() { + if (x) a(); + } + `, + ` + function foo() { + x && a(); + } + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn if statement to conditional", + ` + function foo() { + if (x) a(); + else b(); + } + `, + ` + function foo() { + x ? a() : b(); + } + ` + ); - it("should turn this into a conditional", () => { - const source = unpad(` - function foo(a) { - if (a && a.b != null) { - if ((a.c--) === 1) { - delete a.c; - } - return a.b; + thePlugin( + "should turn this into a conditional", + ` + function foo(a) { + if (a && a.b != null) { + if ((a.c--) === 1) { + delete a.c; } - return bar(a); + return a.b; } - `); - const expected = unpad(` - function foo(a) { - return a && a.b != null ? (a.c-- === 1 && delete a.c, a.b) : bar(a); - } - `); - - expect(transform(source)).toBe(expected); - }); + return bar(a); + } + `, + ` + function foo(a) { + return a && a.b != null ? (a.c-- === 1 && delete a.c, a.b) : bar(a); + } + ` + ); - it("should turn this into a conditional", () => { - const source = unpad(` - function foo(a) { - if (a) { - return a.b; - } else { - return bar(a); + thePlugin( + "should turn this into a conditional", + ` + function foo(a) { + if (a && a.b != null) { + if ((a.c--) === 1) { + delete a.c; } + return a.b; } - `); - const expected = unpad(` - function foo(a) { - return a ? a.b : bar(a); - } - `); - - expect(transform(source)).toBe(expected); - }); + return bar(a); + } + `, + ` + function foo(a) { + return a && a.b != null ? (a.c-- === 1 && delete a.c, a.b) : bar(a); + } + ` + ); - xit("should turn IIFE to negation", () => { - const source = unpad(` - (function() { - x(); - })(); - y = function () { - x(); - }(); - `); - const expected = unpad(` - !function () { - x(); - }(), y = function () { - x(); - }(); - `); + thePlugin( + "should turn this into a conditional", + ` + function foo(a) { + if (a) { + return a.b; + } else { + return bar(a); + } + } + `, + ` + function foo(a) { + return a ? a.b : bar(a); + } + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin.skip( + "should turn IIFE to negation", + ` + (function() { + x(); + })(); + y = function () { + x(); + }(); + `, + ` + !function () { + x(); + }(), y = function () { + x(); + }(); + ` + ); - it("should remove the else block if early return", () => { - const source = unpad(` + thePlugin( + "should remove the else block if early return", + ` function foo() { if (1) { return 2; @@ -220,2520 +214,2304 @@ describe("simplify-plugin", () => { lol(2); } } - `); - - const expected = unpad(` - function foo() { - return 1 ? 2 : void (lol(1), lol(2)); - } - `); + `, + ` + function foo() { + return 1 ? 2 : void (lol(1), lol(2)); + } + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should merge blocks into a return with sequence expr", + ` + function foo() { + y(); + x(); + return 1; + } + `, + ` + function foo() { + return y(), x(), 1; + } + ` + ); - it("should merge blocks into a return with sequence expr", () => { - const source = unpad(` - function foo() { - y(); + thePlugin( + "should merge blocks into a return with sequence expr", + ` + function foo() { + try { x(); - return 1; - } - `); - - const expected = unpad(` - function foo() { - return y(), x(), 1; - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should merge blocks into a return with sequence expr", () => { - const source = unpad(` - function foo() { - try { - x(); - } catch (e) { - 1; - } - - y(); - return 1; - } - `); - - const expected = unpad(` - function foo() { - try { - x(); - } catch (e) { - 1; - } - - return y(), 1; + } catch (e) { + 1; } - `); - expect(transform(source)).toBe(expected); - }); - - // https://github.com/babel/babili/issues/208 - it("should handle empty blocks when merging to sequences", () => { - const source = unpad(` - !function () { - var x; - { } - alert(x); - }() - `); - const expected = unpad(` - !function () { - var x; - alert(x); - }(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should merge expressions into the init part of for", () => { - const source = unpad(` - function foo() { + y(); + return 1; + } + `, + ` + function foo() { + try { x(); - y(); - for (; i < 10; i++) z(); - } - `); - - const expected = unpad(` - function foo() { - for (x(), y(); i < 10; i++) z(); + } catch (e) { + 1; } - `); - - expect(transform(source).trim()).toBe(expected); - }); - it("should merge statements into the init part of for even when there are others", () => { - const source = unpad(` - function foo() { - x(); - y(); - for (z(); i < 10; i++) z(); - } - `); + return y(), 1; + } + ` + ); - const expected = unpad(` - function foo() { - for (x(), y(), z(); i < 10; i++) z(); - } - `); + // https://github.com/babel/babili/issues/208 + thePlugin( + "should handle empty blocks when merging to sequences", + ` + !function () { + var x; + { } + alert(x); + }() + `, + ` + !function () { + var x; + alert(x); + }(); + ` + ); - expect(transform(source).trim()).toBe(expected); - }); + thePlugin( + "should merge expressions into the init part of for", + ` + function foo() { + x(); + y(); + for (; i < 10; i++) z(); + } + `, + ` + function foo() { + for (x(), y(); i < 10; i++) z(); + } + ` + ); - it("should remove empty returns", () => { - const source = unpad(` - function foo() { - lol(); - return; - } - `); + thePlugin( + "should merge statements into the init part of for even when there are others", + ` + function foo() { + x(); + y(); + for (z(); i < 10; i++) z(); + } + `, + ` + function foo() { + for (x(), y(), z(); i < 10; i++) z(); + } + ` + ); - const expected = unpad(` - function foo() { - lol(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should merge if statements with following expressions using void", () => { - const source = unpad(` - function foo() { - if(window.self != window.top) { - if(__DEV__) { - console.log('lol', name); - } - return; - } - lol(); - } - `); + thePlugin( + "should remove empty returns", + ` + function foo() { + lol(); + return; + } + `, + ` + function foo() { + lol(); + } + ` + ); - const expected = unpad(` - function foo() { - return window.self == window.top ? void lol() : void (__DEV__ && console.log('lol', name)); + thePlugin( + "should merge if statements with following expressions using void", + ` + function foo() { + if(window.self != window.top) { + if(__DEV__) { + console.log('lol', name); } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not try to merge `if` when there are multiple statements to follow", () => { - const source = unpad(` - function foo() { - if(window.self != window.top) { - if(__DEV__) { - console.log('lol', name); - } - return; + return; + } + lol(); + } + `, + ` + function foo() { + return window.self == window.top ? void lol() : void (__DEV__ && console.log('lol', name)); + } + ` + ); + + thePlugin( + "should not try to merge `if` when there are multiple statements to follow", + ` + function foo() { + if(window.self != window.top) { + if(__DEV__) { + console.log('lol', name); } - lol(); - try { lol() } catch (e) {} + return; } - `); + lol(); + try { lol() } catch (e) {} + } + `, + ` + function foo() { + if (window.self != window.top) return void (__DEV__ && console.log('lol', name)); + lol(); - const expected = unpad(` - function foo() { - if (window.self != window.top) return void (__DEV__ && console.log('lol', name)); + try { lol(); + } catch (e) {} + } + ` + ); - try { - lol(); - } catch (e) {} - } - `); + thePlugin( + "should handle missing return arg when merging if statements", + ` + function foo() { + if (a) { + return; + } - expect(transform(source)).toBe(expected); - }); + return wow; + } + `, + ` + function foo() { + return a ? void 0 : wow; + } + ` + ); - it("should handle missing return arg when merging if statements", () => { - const source = unpad(` - function foo() { - if (a) { + thePlugin( + "should handle returns with no args", + ` + function foo(a) { + if (a && a.b != null) { + if ((a.c--) === 1) { return; } - - return wow; + return a.b; } - `); + return bar(a); + } + `, + ` + function foo(a) { + return a && a.b != null ? a.c-- === 1 ? void 0 : a.b : bar(a); + } + ` + ); - const expected = unpad(` - function foo() { - return a ? void 0 : wow; + thePlugin( + "should convert whiles to fors", + ` + function foo(a) { + while(true) { + bar(); } - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function foo(a) { + for (; true;) bar(); + } + ` + ); - it("should handle returns with no args", () => { - const source = unpad(` - function foo(a) { - if (a && a.b != null) { - if ((a.c--) === 1) { - return; - } - return a.b; - } - return bar(a); - } - `); - const expected = unpad(` - function foo(a) { - return a && a.b != null ? a.c-- === 1 ? void 0 : a.b : bar(a); + thePlugin( + "should convert whiles to fors and merge vars", + ` + function foo() { + let bar = baz; + while(true) { + bar(); } - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function foo() { + for (let bar = baz; true;) bar(); + } + ` + ); - it("should convert whiles to fors", () => { - const source = unpad(` - function foo(a) { - while(true) { - bar(); - } - } - `); - const expected = unpad(` - function foo(a) { - for (; true;) bar(); + // https://github.com/babel/babili/issues/198 + thePlugin( + "should convert while->for and NOT merge let/const if any is refereced outside the loop", + ` + function foo() { + let a, + { b } = x; + while (true) { + bar(a, b); } - `); - - expect(transform(source)).toBe(expected); - }); + return [a, b]; + } + `, + ` + function foo() { + let a, + { b } = x; - it("should convert whiles to fors and merge vars", () => { - const source = unpad(` - function foo() { - let bar = baz; - while(true) { - bar(); - } - } - `); - const expected = unpad(` - function foo() { - for (let bar = baz; true;) bar(); - } - `); + for (; true;) bar(a, b); - expect(transform(source)).toBe(expected); - }); + return [a, b]; + } + ` + ); - // https://github.com/babel/babili/issues/198 - it("should convert while->for and NOT merge let/const if any is refereced outside the loop", () => { - const source = unpad(` - function foo() { - let a, - { b } = x; - while (true) { - bar(a, b); - } - return [a, b]; + thePlugin( + "should convert while->for and merge var even if any is refereced outside the loop", + ` + function foo() { + var a = 1; + while (true) { + bar(a); } - `); - const expected = unpad(` - function foo() { - let a, - { b } = x; - - for (; true;) bar(a, b); + return a; + } + `, + ` + function foo() { + for (var a = 1; true;) bar(a); - return [a, b]; - } - `); - expect(transform(source)).toBe(expected); - }); + return a; + } + ` + ); - it("should convert while->for and merge var even if any is refereced outside the loop", () => { - const source = unpad(` - function foo() { - var a = 1; - while (true) { - bar(a); - } - return a; - } - `); - const expected = unpad(` - function foo() { - for (var a = 1; true;) bar(a); - - return a; - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should combine returns", () => { - const source = unpad(` - function foo() { - if (a) { - if (a.b) { - if(a.b.c) { - if(a.b.c()){ - return; - } + thePlugin( + "should combine returns", + ` + function foo() { + if (a) { + if (a.b) { + if(a.b.c) { + if(a.b.c()){ + return; } } } - for (; true;) wat(); } - `); + for (; true;) wat(); + } + `, + ` + function foo() { + if (!(a && a.b && a.b.c && a.b.c())) for (; true;) wat(); + } + ` + ); - const expected = unpad(` - function foo() { - if (!(a && a.b && a.b.c && a.b.c())) for (; true;) wat(); + thePlugin( + "should convert early returns to negated if blocks", + ` + function foo(a) { + if (lol) return; + doThings(); + doOtherThings(); + } + function bar(a) { + if (lol) { + return; } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should convert early returns to negated if blocks", () => { - const source = unpad(` - function foo(a) { - if (lol) return; + try { doThings(); + } catch (e) { doOtherThings(); } - function bar(a) { - if (lol) { - return; - } - try { + } + function baz() { + while (wow) if (lol) return; + boo(); + } + `, + ` + function foo(a) { + lol || (doThings(), doOtherThings()); + } + function bar(a) { + if (!lol) try { doThings(); } catch (e) { doOtherThings(); } - } - function baz() { - while (wow) if (lol) return; - boo(); - } - `); - const expected = unpad(` - function foo(a) { - lol || (doThings(), doOtherThings()); - } - function bar(a) { - if (!lol) try { - doThings(); - } catch (e) { - doOtherThings(); - } - } - function baz() { - for (; wow;) if (lol) return; - - boo(); - } + } + function baz() { + for (; wow;) if (lol) return; - `); - expect(transform(source)).toBe(expected); - }); + boo(); + } + ` + ); - it("should remove early return when no other statements", () => { - const source = unpad(` - function foo() { - wow(); - if (x) { - return; - } + thePlugin( + "should remove early return when no other statements", + ` + function foo() { + wow(); + if (x) { + return; } - `); + } + `, + ` + function foo() { + wow(); + x; + } + ` + ); - const expected = unpad(` - function foo() { - wow(); - x; - } - `); - expect(transform(source)).toBe(expected); - }); - - it("earlyReturnTransform: it shouldn't error on shorthand arrow functions", () => { - const source = unpad(` - const f = () => a; - `); - const expected = unpad(` - const f = () => a; - `); - expect(transform(source)).toBe(expected); - }); - - it("should merge function blocks into sequence expressions", () => { - const source = unpad(` - function foo() { - a(); - var x = bar(); - b(x); - this.d = x; - } - function bar() { - x(); - while (x) { - if (x) x(); - } - try { y(); } catch (e) {} - var z = x(); - z(); - while (a) b(); - c(); - z(); - } - `); - - // TODO merge var z into the init part of for. - const expected = unpad(` - function foo() { - a(); + thePlugin( + "earlyReturnTransform: it shouldn't error on shorthand arrow functions", + ` + const f = () => a; + `, + ` + const f = () => a; + ` + ); - var x = bar(); - b(x), this.d = x; - } - function bar() { - for (x(); x;) x && x(); + // TODO merge var z into the init part of for. + thePlugin( + "should merge function blocks into sequence expressions", + ` + function foo() { + a(); + var x = bar(); + b(x); + this.d = x; + } + function bar() { + x(); + while (x) { + if (x) x(); + } + try { y(); } catch (e) {} + var z = x(); + z(); + while (a) b(); + c(); + z(); + } + `, + ` + function foo() { + a(); - try { - y(); - } catch (e) {} - var z = x(); + var x = bar(); + b(x), this.d = x; + } + function bar() { + for (x(); x;) x && x(); - for (z(); a;) b(); + try { + y(); + } catch (e) {} + var z = x(); - c(), z(); - } - `); + for (z(); a;) b(); - expect(transform(source)).toBe(expected); - }); + c(), z(); + } + ` + ); - it("should merge function blocks into sequence expressions (part 2)", () => { - const source = unpad(` - function bar() { - var z; - c(); - for (z in { a: 1}) x(z); - z(); - } - `); + thePlugin( + "should merge function blocks into sequence expressions (part 2)", + ` + function bar() { + var z; + c(); + for (z in { a: 1}) x(z); + z(); + } + `, + ` + function bar() { + var z; - const expected = unpad(` - function bar() { - var z; + for (z in c(), { a: 1 }) x(z); + z(); + } + ` + ); - for (z in c(), { a: 1 }) x(z); - z(); + thePlugin( + "should merge if statements when there is no alternate", + ` + if (a) { + if (b) { + throw 'wow'; } - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + if (a && b) throw 'wow'; + ` + ); - it("should merge if statements when there is no alternate", () => { - const source = unpad(` + thePlugin( + "should not merge if statements if changes semantics", + // FIXME: for some reason, the inner `if` statement gets indented 4 spaces. + ` + function foo() { if (a) { - if (b) { - throw 'wow'; - } - } - `); + if (b()) return false; + } else if (c()) return true; + } + ` + ); - const expected = unpad(` - if (a && b) throw 'wow'; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should merge if/return statements", + ` + function foo() { + if (a) return b; + if (c) return d; + return e; + } + `, + ` + function foo() { + return a ? b : c ? d : e; + } + ` + ); - it("should not merge if statements if changes semantics", () => { - const source = unpad(` - function foo() { - if (a) { - if (b()) return false; - } else if (c()) return true; - } - `); + thePlugin( + "should merge if/return statements 2", + ` + function foo() { + if (bar) return; + if (far) return; + if (faz) return; +1 + return e; + } + `, + ` + function foo() { + return bar || far || faz ? void 0 : e; + } + ` + ); - const expected = unpad(` - function foo() { - if (a) { - if (b()) return false; - } else if (c()) return true; - } - `); + thePlugin( + "should merge return statements with expression in between", + ` + function foo() { + if (a) return b; + c = d; + return z; + } + `, + ` + function foo() { + return a ? b : (c = d, z); + } + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should hoist functions", + ` + function foo() { + a(); + function bar() {} + b(); + } + `, + ` + function foo() { + function bar() {} + a(), b(); + } + ` + ); - it("should merge if/return statements", () => { - const source = unpad(` - function foo() { - if (a) return b; - if (c) return d; - return e; + thePlugin( + "should not return inside a loop", + ` + function foo() { + while(1) { + if (a === null) { + b(); + return; + } + a(); + b(); } - `); - - const expected = unpad(` - function foo() { - return a ? b : c ? d : e; + } + `, + ` + function foo() { + for (; 1;) { + if (a === null) return void b(); + a(), b(); } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should merge if/return statements 2", () => { - const source = unpad(` - function foo() { - if (bar) return; - if (far) return; - if (faz) return; + } + ` + ); - return e; + thePlugin( + "should make if with one return into a conditional", + ` + function foo() { + if (b) { + return foo; + } else { + a(); + b(); } - `); + } + `, + ` + function foo() { + return b ? foo : void (a(), b()); + } + ` + ); - const expected = unpad(` - function foo() { - return bar || far || faz ? void 0 : e; + thePlugin( + "should make if with one return into a conditional 2", + ` + function foo() { + if (b) { + foo(); + } else { + return bar; } - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function foo() { + return b ? void foo() : bar; + } + ` + ); - it("should merge return statements with expression in between", () => { - const source = unpad(` - function foo() { - if (a) return b; - c = d; - return z; + thePlugin( + "should make if with one return into a conditional 3", + ` + function foo() { + if (b) { + foo(); + } else { + return; } - `); + } + `, + ` + function foo() { + b && foo(); + } + ` + ); - const expected = unpad(` - function foo() { - return a ? b : (c = d, z); + thePlugin( + "should make if with one return into a conditional 4", + ` + function foo() { + if (b) { + return; + } else { + foo(); } - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function foo() { + b || foo(); + } + ` + ); - it("should hoist functions", () => { - const source = unpad(` - function foo() { - a(); - function bar() {} - b(); + thePlugin( + "should not merge if", + ` + if (x) { + try { + foo(); + } catch (e) {} + } else if (y) { + if (a) { + bar(); + } else if (b) { + baz(); + } else { + for (;;) 1; } - `); + } + `, + ` + if (x) try { + foo(); + } catch (e) {} else if (y) if (a) bar();else if (b) baz();else for (;;) 1; + ` + ); - const expected = unpad(` - function foo() { - function bar() {} - a(), b(); - } - `); + it("should merge expressions into if statements test"); + it("should understand continue statements"); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should handle do while statements", + ` + do { + foo(); + } while (1); + `, + ` + do foo(); while (1); + ` + ); - it("should not return inside a loop", () => { - const source = unpad(` - function foo() { - while(1) { - if (a === null) { - b(); - return; - } - a(); - b(); - } + thePlugin( + "should handle multiple interplays of if statements and returns", + ` + function lawl() { + var a = 1; + if (b) { + return c; } - `); - const expected = unpad(` - function foo() { - for (; 1;) { - if (a === null) return void b(); - a(), b(); - } + if (a) { + bar(); + return; } - `); - - expect(transform(source)).toBe(expected); - }); - it("should make if with one return into a conditional", () => { - const source = unpad(` - function foo() { - if (b) { - return foo; - } else { - a(); - b(); + if (d) { + if (g) { + this['s'] = morebutts; + return wat; } + return boo; } - `); - const expected = unpad(` - function foo() { - return b ? foo : void (a(), b()); - } - `); + haha(); + return butts; + } + `, + ` + function lawl() { + var a = 1; + return b ? c : a ? void bar() : d ? g ? (this['s'] = morebutts, wat) : boo : (haha(), butts); + } + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should handle empty blocks in if statements", + ` + if (a) { + } else { + foo(); + } - it("should make if with one return into a conditional 2", () => { - const source = unpad(` - function foo() { - if (b) { - foo(); - } else { - return bar; - } - } - `); + if (a) { + foo(); + } else if (b) { + } - const expected = unpad(` - function foo() { - return b ? void foo() : bar; - } - `); + if (a) { + } else { + } + `, + ` + a || foo(), a ? foo() : b, a; + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "re-arrange conditionals for assignment", + ` + var x; + if (a) { + x = foo; + } else if (b) { + x = bar; + } else { + x = baz; + } + `, + ` + var x; + x = a ? foo : b ? bar : baz; + ` + ); - it("should make if with one return into a conditional 3", () => { - const source = unpad(` - function foo() { - if (b) { - foo(); - } else { - return; - } - } - `); + thePlugin( + "should bail on re-arranging conditionals for assignment", + ` + var x; + if (a) { + x = foo; + } else if (b) { + x = bar; + } else { + y = baz; + } + `, + ` + var x; + a ? x = foo : b ? x = bar : y = baz; + ` + ); - const expected = unpad(` - function foo() { - b && foo(); - } - `); + thePlugin( + "should bail on re-arranging conditionals for assignment", + ` + var x; + if (a) { + x = foo; + } else if (b) { + x = bar; + } else { + baz(); + } + `, + ` + var x; + a ? x = foo : b ? x = bar : baz(); + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "re-arranging conditionals for assignment member exprs", + ` + if (a) { + x.b = foo; + } else if (b) { + x.b = bar; + } else { + x.b = baz; + } + `, + ` + x.b = a ? foo : b ? bar : baz; + ` + ); - it("should make if with one return into a conditional 4", () => { - const source = unpad(` - function foo() { - if (b) { - return; - } else { - foo(); - } - } - `); + thePlugin( + "re-arranging conditionals for assignment with operators", + ` + if (a) { + x.b += foo; + } else if (b) { + x.b += bar; + } else { + x.b += baz; + } + `, + ` + x.b += a ? foo : b ? bar : baz; + ` + ); - const expected = unpad(` - function foo() { - b || foo(); - } - `); + thePlugin( + "should bail on different operators", + ` + if (a) { + x.b += foo; + } else if (b) { + x.b -= bar; + } else { + x.b += baz; + } + `, + ` + a ? x.b += foo : b ? x.b -= bar : x.b += baz; + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should bail on different member exprs", + ` + if (a) { + this.a = 1; + } else { + this.b = 2; + } + `, + ` + a ? this.a = 1 : this.b = 2; + ` + ); - it("should not merge if", () => { - const source = unpad(` - if (x) { - try { - foo(); - } catch (e) {} - } else if (y) { - if (a) { - bar(); - } else if (b) { - baz(); - } else { - for (;;) 1; - } - } - `); + thePlugin( + "should turn continue into negated if", + ` + for (var p in foo) { + if (p) continue; + bar(); + } + `, + ` + for (var p in foo) p || bar(); + ` + ); - const expected = unpad(` - if (x) try { - foo(); - } catch (e) {} else if (y) if (a) bar();else if (b) baz();else for (;;) 1; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should flip logical expressions", + ` + !x && foo(); + if (!(null == r)) for (;;); + `, + ` + if (!x && foo(), null != r) for (;;); + ` + ); - it("should merge expressions into if statements test"); - it("should understand continue statements"); + thePlugin( + "should flip logical expressions 2", + ` + if (!(1 !== foo || !bar)) for (;;); + `, + ` + if (1 === foo && bar) for (;;); + ` + ); - it("should handle do while statements", () => { - const source = unpad(` - do { - foo(); - } while (1); - `); - - const expected = unpad(` - do foo(); while (1); - `); - expect(transform(source)).toBe(expected); - }); - - it("should handle multiple interplays of if statements and returns", () => { - const source = unpad(` - function lawl() { - var a = 1; - if (b) { - return c; - } + thePlugin( + "should combine to a single return statement", + ` + function foo() { + if (foo) { + bar(foo); + return foo; + } else if (baz) { + bar(baz); + return baz; + } else if (wat) { + bar(wat); + return wat; + } + } + `, + ` + function foo() { + return foo ? (bar(foo), foo) : baz ? (bar(baz), baz) : wat ? (bar(wat), wat) : void 0; + } + ` + ); - if (a) { - bar(); - return; - } + thePlugin( + "should inline break condition in for test", + ` + for (i = 1; i <= j; i++) { + if (bar) break; + } + `, + ` + for (i = 1; i <= j && !bar; i++); + ` + ); - if (d) { - if (g) { - this['s'] = morebutts; - return wat; - } - return boo; - } + thePlugin( + "should inline break condition in for test 2", + ` + for (i = 1; i <= j; i++) { + foo(); + if (bar) break; + } + `, + ` + for (i = 1; i <= j && (foo(), !bar); i++); + ` + ); - haha(); - return butts; + thePlugin( + "should inline break condition in for test 3", + ` + for (i = 1; i <= j; i++) { + if (bar) { + break; + } else { + wat(); + if (x) throw 1 } - `); + } + `, + ` + for (i = 1; i <= j && !bar; i++) if (wat(), x) throw 1; + ` + ); - const expected = unpad(` - function lawl() { - var a = 1; - return b ? c : a ? void bar() : d ? g ? (this['s'] = morebutts, wat) : boo : (haha(), butts); + // TODO: see `!!` below. + thePlugin( + "should inline break condition in for test 4", + ` + for (i = 1; i <= j; i++) { + if (bar) { + wat(); + if (x) throw 1; + } else { + break; } - `); - expect(transform(source)).toBe(expected); - }); + } + `, + ` + for (i = 1; i <= j && !!bar; i++) if (wat(), x) throw 1; + ` + ); - it("should handle empty blocks in if statements", () => { - const source = unpad(` - if (a) { + // TODO: only apply ! unary to last in seq expr + thePlugin( + "should inline break condition in for test 5", + ` + for (i = 1; i <= j; i++) { + foo(); + if (bar) { + break; } else { - foo(); + wat(); + if (x) throw 1 } + hi(); + } + `, + ` + for (i = 1; i <= j && (foo(), !bar); i++) { + if (wat(), x) throw 1; + hi(); + } + ` + ); - if (a) { - foo(); - } else if (b) { + thePlugin( + "should merge conditional returns into test", + ` + function foo() { + if (x) { + delete x.x; + if (bar()) return; } - if (a) { + if (bar) { + x(); } else { + y(); } - `); - - const expected = unpad(` - a || foo(), a ? foo() : b, a; - `); - - expect(transform(source)).toBe(expected); - }); - - it("re-arrange conditionals for assignment", () => { - const source = unpad(` - var x; - if (a) { - x = foo; - } else if (b) { - x = bar; - } else { - x = baz; - } - `); - - const expected = unpad(` - var x; - x = a ? foo : b ? bar : baz; - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function foo() { + x && (delete x.x, bar()) || (bar ? x() : y()); + } + ` + ); - it("should bail on re-arranging conditionals for assignment", () => { - const source = unpad(` - var x; - if (a) { - x = foo; - } else if (b) { - x = bar; - } else { - y = baz; + thePlugin( + "should bail on mrege conditional return into test", + ` + function foo() { + if (x) { + delete x.x; + if (bar()) return 2; } - `); - - const expected = unpad(` - var x; - a ? x = foo : b ? x = bar : y = baz; - `); - - expect(transform(source)).toBe(expected); - }); - it("should bail on re-arranging conditionals for assignment", () => { - const source = unpad(` - var x; - if (a) { - x = foo; - } else if (b) { - x = bar; + if (bar) { + x(); } else { - baz(); + y(); } - `); - - const expected = unpad(` - var x; - a ? x = foo : b ? x = bar : baz(); - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function foo() { + return x && (delete x.x, bar()) ? 2 : void (bar ? x() : y()); + } + ` + ); - it("re-arranging conditionals for assignment member exprs", () => { - const source = unpad(` - if (a) { - x.b = foo; - } else if (b) { - x.b = bar; - } else { - x.b = baz; + thePlugin( + "should merge conditional return into test 2", + ` + function foo() { + if (x) { + delete x.x; + if (bar()) return; } - `); - - const expected = unpad(` - x.b = a ? foo : b ? bar : baz; - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function foo() { + x && (delete x.x, bar()); + } + ` + ); - it("re-arranging conditionals for assignment with operators", () => { - const source = unpad(` - if (a) { - x.b += foo; - } else if (b) { - x.b += bar; - } else { - x.b += baz; + thePlugin( + "should handle return argument", + ` + function foo() { + if (x) { + delete x.x; + if (bar()) return x; } - `); - - const expected = unpad(` - x.b += a ? foo : b ? bar : baz; - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function foo() { + if (x && (delete x.x, bar())) return x; + } + ` + ); - it("should bail on different operators", () => { - const source = unpad(` - if (a) { - x.b += foo; - } else if (b) { - x.b -= bar; - } else { - x.b += baz; + thePlugin( + "should bail on conditional return into test", + ` + function foo() { + if (x) { + var f = wow; + delete x.x; + if (bar()) return; } - `); - - const expected = unpad(` - a ? x.b += foo : b ? x.b -= bar : x.b += baz; - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function foo() { + if (x) { + var f = wow; - it("should bail on different member exprs", () => { - const source = unpad(` - if (a) { - this.a = 1; - } else { - this.b = 2; + if (delete x.x, bar()) return; } - `); - - const expected = unpad(` - a ? this.a = 1 : this.b = 2; - `); + } + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should recombine after continue merging", + ` + for (;;) { + a = b; + if (!foo) continue; + bar = foo; + } + `, + ` + for (;;) a = b, foo && (bar = foo); + ` + ); - it("should turn continue into negated if", () => { - const source = unpad(` - for (var p in foo) { - if (p) continue; - bar(); + thePlugin( + "should not assume undefined", + ` + function foo() { + if (foo) { + if (bar) { + return false; + } + if (baz) { + return false; + } } - `); - - const expected = unpad(` - for (var p in foo) p || bar(); - `); - - expect(transform(source)).toBe(expected); - }); - - it("should flip logical expressions", () => { - const source = unpad(` - !x && foo(); - if (!(null == r)) for (;;); - `); - - const expected = unpad(` - if (!x && foo(), null != r) for (;;); - `); - - expect(transform(source).trim()).toBe(expected.trim()); - }); - - it("should flip logical expressions 2", () => { - const source = unpad(` - if (!(1 !== foo || !bar)) for (;;); - `); + return true; + } + `, + ` + function foo() { + if (foo) { + if (bar) return false; + if (baz) return false; + } + return true; + } + ` + ); - const expected = unpad(` - if (1 === foo && bar) for (;;); - `); + thePlugin( + "should keep directives", + ` + function a() { + 'use strict'; + foo(); + } + `, + ` + function a() { + 'use strict'; - expect(transform(source)).toBe(expected); - }); + foo(); + } + ` + ); - it("should combine to a single return statement", () => { - const source = unpad(` - function foo() { + thePlugin( + "should handle continue in nested if", + ` + function wow() { + for(;;) { if (foo) { - bar(foo); - return foo; - } else if (baz) { - bar(baz); - return baz; - } else if (wat) { - bar(wat); - return wat; + if (bar) { + continue; + } } + wat(); } - `); - - const expected = unpad(` - function foo() { - return foo ? (bar(foo), foo) : baz ? (bar(baz), baz) : wat ? (bar(wat), wat) : void 0; - } - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function wow() { + for (;;) foo && bar || wat(); + } + ` + ); - it("should inline break condition in for test", () => { - const source = unpad(` - for (i = 1; i <= j; i++) { - if (bar) break; - } - `); + thePlugin( + "should convert gaurded nots to ors", + ` + x(); + if (!foo.bar) foo.bar = wat; + `, + ` + x(), !foo.bar && (foo.bar = wat); + ` + ); - const expected = unpad(` - for (i = 1; i <= j && !bar; i++); - `); + thePlugin( + "should convert gaurded nots to ors", + ` + if (!foo && foo !== bar) { + wow(); + such(); + } + `, + ` + !foo && foo !== bar && (wow(), such()); + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should put the empty vars first", + ` + var x = 1, y, z = 2, zx, a; + `, + ` + var y, + zx, + a, + x = 1, + z = 2; + ` + ); + + thePlugin( + "function expression in sequennce doesnt need parens", + ` + x, (function() {})(); + `, + ` + x, function () {}(); + ` + ); - it("should inline break condition in for test 2", () => { - const source = unpad(` - for (i = 1; i <= j; i++) { - foo(); - if (bar) break; + thePlugin( + "should turn early return else block into statement", + ` + function x() { + for (;;) { + x(); + if (foo) return 1; + else y(); } - `); - - const expected = unpad(` - for (i = 1; i <= j && (foo(), !bar); i++); - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function x() { + for (;;) { + if (x(), foo) return 1; + y(); + } + } + ` + ); - it("should inline break condition in for test 3", () => { - const source = unpad(` - for (i = 1; i <= j; i++) { - if (bar) { - break; - } else { - wat(); - if (x) throw 1 + thePlugin( + "should remove block", + ` + function x() { + if (a) { + if (b) { + for(;;) { + if (a) b(); + } } + } else { + wat(); } - `); - - const expected = unpad(` - for (i = 1; i <= j && !bar; i++) if (wat(), x) throw 1; - `); + } + `, + ` + function x() { + if (!a) wat();else if (b) for (;;) a && b(); + } + ` + ); - expect(transform(source)).toBe(expected); - }); + // TODO + thePlugin( + "should merge things into throw statement seq expr", + ` + function x() { + z(); + throw y; + } + `, + ` + function x() { + throw z(), y; + } + ` + ); - it("should inline break condition in for test 4", () => { - const source = unpad(` - for (i = 1; i <= j; i++) { - if (bar) { - wat(); - if (x) throw 1; - } else { - break; + // TODO: + // Fix indenting + thePlugin( + "should negate early return if", + ` + function x() { + if (!bar) return; + var x = foo; + if (!foo) return + if (y) + throw y; + } + `, + ` + function x() { + if (bar) { + var x = foo; + if (foo && y) throw y; } + } + ` + ); + + thePlugin( + "should not negate early return if", + ` + function x() { + var x = foo; + if (hi) { + var y = z; + if (!foo) return; + if (x) throw y; + } + x(); + } + `, + ` + function x() { + var x = foo; + if (hi) { + var y = z; + if (!foo) return; + if (x) throw y; } - `); + x(); + } + ` + ); - // TODO: see `!!` below. - const expected = unpad(` - for (i = 1; i <= j && !!bar; i++) if (wat(), x) throw 1; - `); + thePlugin( + "switch if to avoid blocking", + ` + function x() { + if (a) { + if (b) for (;;) wow(); + } else c(); + } + `, + ` + function x() { + if (!a) c();else if (b) for (;;) wow(); + } + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should remove last break statement in switch", + ` + switch (foo) { + case 'foo': + throw bar(); + break; + case 'bar': + wow(); + break; + } + `, + ` + switch (foo) { + case 'foo': + throw bar(); + break; + case 'bar': + wow(); - it("should inline break condition in for test 5", () => { - const source = unpad(` - for (i = 1; i <= j; i++) { - foo(); - if (bar) { + } + ` + ); + + thePlugin( + "should not remove last break statement if it contains a label", + ` + loop: while (foo) { + switch (bar) { + case 47: break; - } else { - wat(); - if (x) throw 1 - } - hi(); } - `); - - // TODO: only apply ! unary to last in seq expr - const expected = unpad(` - for (i = 1; i <= j && (foo(), !bar); i++) { - if (wat(), x) throw 1; - hi(); + switch (baz) { + default: + break loop; } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should merge conditional returns into test", () => { - const source = unpad(` - function foo() { - if (x) { - delete x.x; - if (bar()) return; - } - - if (bar) { - x(); - } else { - y(); - } + } + `, + ` + loop: for (; foo;) { + switch (bar) { + case 47: } - `); - - const expected = unpad(` - function foo() { - x && (delete x.x, bar()) || (bar ? x() : y()); + switch (baz) { + default: + break loop; } - `); + } + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should convert consequents in switch into sequence expressions", + ` + function bar() { + switch (foo) { + case 'foo': + bar(); + foo(); + break; + case 'bar': + wow(); + return wo; + break; + } + } + `, + ` + function bar() { + switch (foo) { + case 'foo': + bar(), foo(); - it("should bail on mrege conditional return into test", () => { - const source = unpad(` - function foo() { - if (x) { - delete x.x; - if (bar()) return 2; - } + break; + case 'bar': + return wow(), wo; - if (bar) { - x(); - } else { - y(); - } } - `); + } + ` + ); - const expected = unpad(` - function foo() { - return x && (delete x.x, bar()) ? 2 : void (bar ? x() : y()); + thePlugin( + "should convert switch statements to returns", + ` + function bar() { + switch (foo) { + case 'foo': + return 1; + case foo.bar: + return 2; + case wow: + wow(); + return 3; + default: + return 0; } - `); + } + `, + ` + function bar() { + return foo === 'foo' ? 1 : foo === foo.bar ? 2 : foo === wow ? (wow(), 3) : 0; + } + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should convert switch statements with next return as default to returns", + ` + function bar() { + switch (foo) { + case 'foo': + return 1; + case foo.bar: + return 2; + case wow: + wow(); + return 3; + } + return 0; + } + `, + ` + function bar() { + return foo === 'foo' ? 1 : foo === foo.bar ? 2 : foo === wow ? (wow(), 3) : 0; + } + ` + ); - it("should merge conditional return into test 2", () => { - const source = unpad(` - function foo() { - if (x) { - delete x.x; - if (bar()) return; - } + thePlugin( + "if last statement in function should consider the default return a void", + ` + function bar() { + switch (foo) { + case 'foo': + return 1; + case foo.bar: + return 2; + case wow: + wow(); + return 3; } - `); + } + `, + ` + function bar() { + return foo === 'foo' ? 1 : foo === foo.bar ? 2 : foo === wow ? (wow(), 3) : void 0; + } + ` + ); - const expected = unpad(` - function foo() { - x && (delete x.x, bar()); + /* eslint-disable max-len */ + thePlugin( + "should convert switch statements w/ fallthrough to return", + ` + function bar() { + switch (foo) { + case 'foo': + return 1; + case foo.bar: + case wow: + wow(); + return 3; + case boo: + return 4; + case baz: + case wat: + return 5; + default: + return 0; } - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function bar() { + return foo === 'foo' ? 1 : foo === foo.bar || foo === wow ? (wow(), 3) : foo === boo ? 4 : foo === baz || foo === wat ? 5 : 0; + } + ` + ); + /* eslint-enable max-len */ - it("should handle return argument", () => { - const source = unpad(` - function foo() { - if (x) { - delete x.x; - if (bar()) return x; - } + thePlugin( + "should convert non-return switch to conditionals", + ` + function bar() { + switch (foo) { + case 'foo': + foo(); + break; + case foo.bar: + wow(); + wat(); + break; + case shh: + case wow: + baa(); + break; + default: + meh(); } - `); + } + `, + ` + function bar() { + foo === 'foo' ? foo() : foo === foo.bar ? (wow(), wat()) : foo === shh || foo === wow ? baa() : meh(); + } + ` + ); - const expected = unpad(` - function foo() { - if (x && (delete x.x, bar())) return x; + thePlugin( + "should put sequence in switch test", + ` + function bar() { + wow(); + switch (foo) { + case 'foo': + throw x(); + break; } - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function bar() { + switch (wow(), foo) { + case 'foo': + throw x(); - it("should bail on conditional return into test", () => { - const source = unpad(` - function foo() { - if (x) { - var f = wow; - delete x.x; - if (bar()) return; - } } - `); - - const expected = unpad(` - function foo() { - if (x) { - var f = wow; + } + ` + ); - if (delete x.x, bar()) return; - } + thePlugin( + "should put sequence in if test", + ` + function bar() { + wow(); + if (foo) { + throw x(); } - `); - - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function bar() { + if (wow(), foo) throw x(); + } + ` + ); - it("should recombine after continue merging", () => { - const source = unpad(` - for (;;) { - a = b; - if (!foo) continue; - bar = foo; + thePlugin( + "should convert non-return switch to conditionals", + ` + function bar() { + switch (foo) { + case 'foo': + foo(); + break; + case foo.bar: + wow(); + wat(); + break; + case shh: + case wow: + baa(); + break; + default: + meh(); } - `); - - const expected = unpad(` - for (;;) a = b, foo && (bar = foo); - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not assume undefined", () => { - const source = unpad(` - function foo() { - if (foo) { - if (bar) { - return false; - } - if (baz) { - return false; - } - } - return true; - } - `); - - const expected = unpad(` - function foo() { - if (foo) { - if (bar) return false; - if (baz) return false; - } - return true; - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should keep directives", () => { - const source = unpad(` - function a() { - 'use strict'; - foo(); - } - `); - - const expected = unpad(` - function a() { - 'use strict'; - - foo(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should handle continue in nested if", () => { - const source = unpad(` - function wow() { - for(;;) { - if (foo) { - if (bar) { - continue; - } - } - wat(); - } - } - `); - - const expected = unpad(` - function wow() { - for (;;) foo && bar || wat(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should convert gaurded nots to ors", () => { - const source = unpad(` - x(); - if (!foo.bar) foo.bar = wat; - `); - - const expected = unpad(` - x(), !foo.bar && (foo.bar = wat); - `); - - expect(transform(source)).toBe(expected); - }); - - it("should convert gaurded nots to ors", () => { - const source = unpad(` - if (!foo && foo !== bar) { - wow(); - such(); - } - `); - - const expected = unpad(` - !foo && foo !== bar && (wow(), such()); - `); - - expect(transform(source)).toBe(expected); - }); - - it("should put the empty vars first", () => { - const source = unpad(` - var x = 1, y, z = 2, zx, a; - `); - - const expected = unpad(` - var y, - zx, - a, - x = 1, - z = 2; - `); - - expect(transform(source)).toBe(expected); - }); - - it("function expression in sequennce doesnt need parens", () => { - const source = unpad(` - x, (function() {})(); - `); - - const expected = unpad(` - x, function () {}(); - `); - - expect(transform(source)).toBe(expected); - }); - - it("should turn early return else block into statement", () => { - const source = unpad(` - function x() { - for (;;) { - x(); - if (foo) return 1; - else y(); - } - } - `); - - const expected = unpad(` - function x() { - for (;;) { - if (x(), foo) return 1; - y(); - } - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should remove block", () => { - const source = unpad(` - function x() { - if (a) { - if (b) { - for(;;) { - if (a) b(); - } - } - } else { - wat(); - } - } - `); - - const expected = unpad(` - function x() { - if (!a) wat();else if (b) for (;;) a && b(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - // TODO - it("should merge things into throw statement seq expr", () => { - const source = unpad(` - function x() { - z(); - throw y; - } - `); - - const expected = unpad(` - function x() { - throw z(), y; - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should negate early return if", () => { - const source = unpad(` - function x() { - if (!bar) return; - var x = foo; - if (!foo) return - if (y) - throw y; - } - `); - - // TODO: - // Fix indenting - const expected = unpad(` - function x() { - if (bar) { - var x = foo; - if (foo && y) throw y; - } - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not negate early return if", () => { - const source = unpad(` - function x() { - var x = foo; - if (hi) { - var y = z; - if (!foo) return; - if (x) throw y; - } - x(); - } - `); - - const expected = unpad(` - function x() { - var x = foo; - if (hi) { - var y = z; - if (!foo) return; - if (x) throw y; - } - x(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("switch if to avoid blocking", () => { - const source = unpad(` - function x() { - if (a) { - if (b) for (;;) wow(); - } else c(); - } - `); - - const expected = unpad(` - function x() { - if (!a) c();else if (b) for (;;) wow(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should remove last break statement in switch", () => { - const source = unpad(` - switch (foo) { - case 'foo': - throw bar(); - break; - case 'bar': - wow(); - break; - } - `); - - const expected = unpad(` - switch (foo) { - case 'foo': - throw bar(); - break; - case 'bar': - wow(); - - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not remove last break statement if it contains a label", () => { - const source = unpad(` - loop: while (foo) { - switch (bar) { - case 47: - break; - } - switch (baz) { - default: - break loop; - } - } - `); - const expected = unpad(` - loop: for (; foo;) { - switch (bar) { - case 47: - } - switch (baz) { - default: - break loop; - } - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should convert consequents in switch into sequence expressions", () => { - const source = unpad(` - function bar() { - switch (foo) { - case 'foo': - bar(); - foo(); - break; - case 'bar': - wow(); - return wo; - break; - } - } - `); - - const expected = unpad(` - function bar() { - switch (foo) { - case 'foo': - bar(), foo(); - - break; - case 'bar': - return wow(), wo; - - } - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should convert switch statements to returns", () => { - const source = unpad(` - function bar() { - switch (foo) { - case 'foo': - return 1; - case foo.bar: - return 2; - case wow: - wow(); - return 3; - default: - return 0; - } - } - `); + } + `, + ` + function bar() { + foo === 'foo' ? foo() : foo === foo.bar ? (wow(), wat()) : foo === shh || foo === wow ? baa() : meh(); + } + ` + ); - const expected = unpad(` - function bar() { - return foo === 'foo' ? 1 : foo === foo.bar ? 2 : foo === wow ? (wow(), 3) : 0; - } - `); + thePlugin( + "should not change type", + ` + function x(a) { + return !!a; + } + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should not change type", + ` + function x(a, b) { + a = a || b; + return b === a || !a; + } + `, + ` + function x(a, b) { + return a = a || b, b === a || !a; + } + ` + ); - it("should convert switch statements with next return as default to returns", () => { - const source = unpad(` - function bar() { - switch (foo) { - case 'foo': - return 1; - case foo.bar: - return 2; - case wow: - wow(); - return 3; - } - return 0; - } - `); + thePlugin( + "should apply unary to only the last element of a sequence expr", + ` + !(a, b, c); + `, + ` + a, b, !c; + ` + ); - const expected = unpad(` - function bar() { - return foo === 'foo' ? 1 : foo === foo.bar ? 2 : foo === wow ? (wow(), 3) : 0; - } - `); + thePlugin( + "should apply unary to both sides of the conditional", + ` + !(a ? b : c); + `, + ` + a ? !b : !c; + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should flip alt and cons if condition is unary", + ` + !(!a && b) ? b : c + `, + ` + !a && b ? c : b; + ` + ); - it("if last statement in function should consider the default return a void", () => { - const source = unpad(` - function bar() { - switch (foo) { - case 'foo': - return 1; - case foo.bar: - return 2; - case wow: - wow(); - return 3; - } - } - `); + thePlugin( + "should merge previous expressions in the for loop right", + ` + function foo() { + x = 1; + a(); + for (var a in b) wow(); + } + `, + ` + function foo() { + for (var a in x = 1, a(), b) wow(); + } + ` + ); - const expected = unpad(` - function bar() { - return foo === 'foo' ? 1 : foo === foo.bar ? 2 : foo === wow ? (wow(), 3) : void 0; - } - `); + thePlugin( + "should convert empty blocks to empty statements", + ` + function foo() { + for (i in p) {} + for (; ;) {} + switch(1) {} + try { a } catch(e) {} + } + `, + ` + function foo() { + for (i in p); + for (;;); + switch (1) {} + try { + a; + } catch (e) {} + } + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should flip binary expressions", + ` + if (!(!a && b == a && !b && b < a)) for(;;) a(); + `, + ` + if (a || b != a || b || !(b < a)) for (;;) a(); + ` + ); - it("should convert switch statements w/ fallthrough to return", () => { - const source = unpad(` - function bar() { - switch (foo) { - case 'foo': - return 1; - case foo.bar: - case wow: - wow(); - return 3; - case boo: - return 4; - case baz: - case wat: - return 5; - default: - return 0; - } - } - `); + // From UglifyJS + thePlugin( + "should simplify common conditional expression patterns", + ` + function f1() { return a == b ? true : x; } + function f2() { return a == b ? false : x; } + function f3() { return a < b ? !0 : x; } + function f4() { return a < b ? !1 : x; } + function f5() { return c ? !0 : x; } + function f6() { return c ? false : x; } + function f7() { return !c ? true : x; } + function f8() { return !c ? !1 : x; } + function g1() { return a == b ? x : true; } + function g2() { return a == b ? x : false; } + function g3() { return a < b ? x : !0; } + function g4() { return a < b ? x : !1; } + function g5() { return c ? x : true; } + function g6() { return c ? x : !1; } + function g7() { return !c ? x : !0; } + function g8() { return !c ? x : false; } + `, + ` + function f1() { + return !(a != b) || x; + } + function f2() { + return a != b && x; + } + function f3() { + return !!(a < b) || x; + } + function f4() { + return !(a < b) && x; + } + function f5() { + return !!c || x; + } + function f6() { + return !c && x; + } + function f7() { + return !c || x; + } + function f8() { + return !!c && x; + } + function g1() { + return a != b || x; + } + function g2() { + return !(a != b) && x; + } + function g3() { + return !(a < b) || x; + } + function g4() { + return !!(a < b) && x; + } + function g5() { + return !c || x; + } + function g6() { + return !!c && x; + } + function g7() { + return !!c || x; + } + function g8() { + return !c && x; + } + ` + ); - /*eslint max-len: 0 */ - const expected = unpad(` - function bar() { - return foo === 'foo' ? 1 : foo === foo.bar || foo === wow ? (wow(), 3) : foo === boo ? 4 : foo === baz || foo === wat ? 5 : 0; - } - `); + // From UglifyJS + thePlugin.inEachLine( + "should simplify logical expression of the following forms of && by compressing to the right", + ` + a = true && foo + a = 1 && console.log("asdf") + a = 4 * 2 && foo() + a = 10 == 10 && foo() + bar() + a = "foo" && foo() + a = 1 + "a" && foo / 10 + a = -1 && 5 << foo + a = 6 && 10 + a = !NaN && foo() + `, + ` + a = foo; + a = console.log("asdf"); + a = foo(); + a = foo() + bar(); + a = foo(); + a = foo / 10; + a = 5 << foo; + a = 10; + a = foo(); + ` + ); + + thePlugin.inEachLine( + "should simplify logical expression of the following forms of && by compressing to the left", + ` + a = false && bar + a = NaN && console.log("a") + a = 0 && bar() + a = undefined && foo(bar) + a = 3 * 3 - 9 && bar(foo) + a = 9 == 10 && foo() + a = !"string" && foo % bar + a = 0 && 7 + `, + ` + a = false; + a = NaN; + a = 0; + a = undefined; + a = 0; + a = false; + a = false; + a = 0; + ` + ); + thePlugin.inEachLine( + "should not simplify invalid logical expression of the following forms of &&", + ` + a = foo() && true; + a = console.log && 3 + 8; + a = foo + bar + 5 && "a"; + a = 4 << foo && -1.5; + a = bar() && false; + a = foo() && 0; + a = bar() && NaN; + a = foo() && null; + ` + ); + + thePlugin.inEachLine( + "should simplify logical expression of the following forms of || by compressing to the left", + ` + a = true || condition; + a = 1 || console.log("a"); + a = 2 * 3 || 2 * condition; + a = 5 == 5 || condition + 3; + a = "string" || 4 - condition; + a = 5 + "" || condition / 5; + a = -4.5 || 6 << condition; + a = 6 || 7; + `, + ` + a = true; + a = 1; + a = 6; + a = true; + a = "string"; + a = "5"; + a = -4.5; + a = 6; + ` + ); + + thePlugin.inEachLine( + "should simplify logical expression of the following forms of || by compressing to the right", + ` + a = false || condition; + a = 0 || console.log("b"); + a = NaN || console.log("c"); + a = undefined || 2 * condition; + a = null || condition + 3; + a = 2 * 3 - 6 || 4 - condition; + a = 10 == 7 || condition / 5; + a = !"string" || 6 % condition; + a = null || 7; + `, + ` + a = condition; + a = console.log("b"); + a = console.log("c"); + a = 2 * condition; + a = condition + 3; + a = 4 - condition; + a = condition / 5; + a = 6 % condition; + a = 7; + ` + ); + + thePlugin.inEachLine( + "should not simplify invald logical expression of the following forms of || by compressing to the right", + ` + a = condition || true; + a = console.log("a") || 2; + a = 4 - condition || "string"; + a = 6 << condition || -4.5; + a = condition || false; + a = console.log("b") || NaN; + a = console.log("c") || 0; + a = 2 * condition || undefined; + a = condition + 3 || null; + ` + ); + + thePlugin.inEachLine( + "should transform complex logical expressions", + ` + a = true && 1 && foo + a = 1 && 4 * 2 && console.log("asdf") + a = 4 * 2 && NaN && foo() + a = 10 == 11 || undefined && foo() + bar() && bar() + a = -1 && undefined || 5 << foo + `, + ` + a = foo; + a = console.log("asdf"); + a = NaN; + a = undefined; + a = 5 << foo; + ` + ); - expect(transform(source)).toBe(expected); - }); + // https://github.com/babel/babili/issues/115 + thePlugin( + "should transform impure conditional statements correctly - issue#115", + ` + (function () { + a = x ? true : false; + c = 1 ? (this.get(x), a = b, true) : (foo.bar, false); + })(); + `, + ` + (function () { + a = !!x, c = 1 ? (this.get(x), a = b, true) : (foo.bar, false); + })(); + ` + ); + + thePlugin( + "should require block for single block scoped declaration in if/else", + ` + if (false) { + let { a } = foo(); + } else if (true) { + const x = bar(); + } else { + function baz() {} + } + ` + ); - it("should convert non-return switch to conditionals", () => { - const source = unpad(` - function bar() { - switch (foo) { - case 'foo': - foo(); - break; - case foo.bar: - wow(); - wat(); - break; - case shh: - case wow: - baa(); - break; - default: - meh(); - } + thePlugin.inEachLine( + "should simplify assignments", + ` + 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; + `, + ` + ++x; + --x; + x *= 1; + x %= 1; + x <<= 1; + x >>= 1; + x >>>= 1; + x &= 1; + x |= 1; + x ^= 1; + x /= 1; + x **= 1; + ` + ); + + thePlugin.inEachLine( + "should not simplify assignments when it is not an equal operator", + ` + 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; + `, + ` + 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; + ` + ); + + thePlugin.inEachLine( + "should not simplify assignments further when it is not an equal operator", + ` + x = x + (x >> 1); + x = x - (x >> 1); + x = x * (x >> 1); + x = x % (x >> 1); + x = x << (x >> 1); + x = x >> (x >> 1); + x = x >>> (x >> 1); + x = x & (x >> 1); + x = x | (x >> 1); + x = x ^ (x >> 1); + x = x / (x >> 1); + x = 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; + x **= x >> 1; + ` + ); + + thePlugin.inEachLine( + "should simplify assignments 2", + ` + foo = foo + bar; + foo = foo * function(){}; + foo += 123; + foo = 1 + foo; + x = x = x + 1; + foo = foo + bar + baz; + `, + ` + foo += bar; + foo *= function () {}; + foo += 123; + foo = 1 + foo; + x = ++x; + foo = foo + bar + baz; + ` + ); + + // TODO: foo[void 0] = foo[void 0] + 1; + thePlugin.inEachLine( + "should simplify assignments w. member expressions", + ` + 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; + foo[null] = foo[null] + 1; + foo[undefined] = foo[undefined] + 1; + foo.bar = foo.bar || {}; + `, + ` + ++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; + ++foo[null]; + ++foo[undefined]; + foo.bar = foo.bar || {}; + ` + ); + + thePlugin( + "should simplify assignments w. super", + ` + class Foo { + foo() { + super.foo = super.foo + 1; } - `); - - const expected = unpad(` - function bar() { - foo === 'foo' ? foo() : foo === foo.bar ? (wow(), wat()) : foo === shh || foo === wow ? baa() : meh(); + }; + `, + ` + class Foo { + foo() { + ++super.foo; } - `); + }; + ` + ); - expect(transform(source)).toBe(expected); - }); - - it("should put sequence in switch test", () => { - const source = unpad(` - function bar() { - wow(); - switch (foo) { - case 'foo': - throw x(); - break; - } + thePlugin( + "should not simplify assignments w. template literals", + ` + foo[\`x\`] = foo[\`x\`] + 1; + ` + ); + + // TODO: + // Fix indenting + thePlugin( + "should consider hoisted definitions in if_return", + ` + function foo() { + bar(); + if(x) return; + const {a}=b; + function bar () { + baz(); + bar(); } - `); - - const expected = unpad(` + } + `, + ` + function foo() { function bar() { - switch (wow(), foo) { - case 'foo': - throw x(); - - } + baz(), bar(); } - `); - - expect(transform(source)).toBe(expected); - }); - it("should put sequence in if test", () => { - const source = unpad(` - function bar() { - wow(); - if (foo) { - throw x(); + if (bar(), !x) { + const { a } = b; } - } - `); - - const expected = unpad(` - function bar() { - if (wow(), foo) throw x(); - } - `); - - expect(transform(source)).toBe(expected); - }); + } + ` + ); - it("should convert non-return switch to conditionals", () => { - const source = unpad(` - function bar() { - switch (foo) { - case 'foo': - foo(); - break; - case foo.bar: - wow(); - wat(); - break; - case shh: - case wow: - baa(); - break; - default: - meh(); - } + thePlugin( + "should optimize if..else..returns", + ` + function foo() { + if (a) { + if (x) return; + else return x; } - `); - - const expected = unpad(` - function bar() { - foo === 'foo' ? foo() : foo === foo.bar ? (wow(), wat()) : foo === shh || foo === wow ? baa() : meh(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("should not change type", () => { - const source = unpad(` - function x(a) { - return !!a; - } - `); - - const expected = unpad(` - function x(a) { - return !!a; - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should not change type", () => { - const source = unpad(` - function x(a, b) { - a = a || b; - return b === a || !a; - } - `); - - const expected = unpad(` - function x(a, b) { - return a = a || b, b === a || !a; - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should apply unary to only the last element of a sequence expr", () => { - const source = unpad(` - !(a, b, c); - `); - - const expected = unpad(` - a, b, !c; - `); - expect(transform(source)).toBe(expected); - }); - - it("should apply unary to both sides of the conditional", () => { - const source = unpad(` - !(a ? b : c); - `); - - const expected = unpad(` - a ? !b : !c; - `); - expect(transform(source)).toBe(expected); - }); - - it("should flip alt and cons if condition is unary", () => { - const source = unpad(` - !(!a && b) ? b : c - `); - - const expected = unpad(` - !a && b ? c : b; - `); - expect(transform(source)).toBe(expected); - }); - - it("should merge previous expressions in the for loop right", () => { - const source = unpad(` - function foo() { - x = 1; - a(); - for (var a in b) wow(); - } - `); - - const expected = unpad(` - function foo() { - for (var a in x = 1, a(), b) wow(); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should convert empty blocks to empty statements", () => { - const source = unpad(` - function foo() { - for (i in p) {} - for (; ;) {} - switch(1) {} - try { a } catch(e) {} - } - `); - - const expected = unpad(` - function foo() { - for (i in p); - for (;;); - switch (1) {} - try { - a; - } catch (e) {} - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should flip binary expressions", () => { - const source = unpad(` - if (!(!a && b == a && !b && b < a)) for(;;) a(); - `); - - const expected = unpad(` - if (a || b != a || b || !(b < a)) for (;;) a(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should simplify common conditional expression patterns", () => { - // From UglifyJS - const source = unpad(` - function f1() { return a == b ? true : x; } - function f2() { return a == b ? false : x; } - function f3() { return a < b ? !0 : x; } - function f4() { return a < b ? !1 : x; } - function f5() { return c ? !0 : x; } - function f6() { return c ? false : x; } - function f7() { return !c ? true : x; } - function f8() { return !c ? !1 : x; } - function g1() { return a == b ? x : true; } - function g2() { return a == b ? x : false; } - function g3() { return a < b ? x : !0; } - function g4() { return a < b ? x : !1; } - function g5() { return c ? x : true; } - function g6() { return c ? x : !1; } - function g7() { return !c ? x : !0; } - function g8() { return !c ? x : false; } - `); - const expected = unpad(` - function f1() { - return !(a != b) || x; - } - function f2() { - return a != b && x; - } - function f3() { - return !!(a < b) || x; - } - function f4() { - return !(a < b) && x; - } - function f5() { - return !!c || x; - } - function f6() { - return !c && x; - } - function f7() { - return !c || x; - } - function f8() { - return !!c && x; - } - function g1() { - return a != b || x; - } - function g2() { - return !(a != b) && x; - } - function g3() { - return !(a < b) || x; - } - function g4() { - return !!(a < b) && x; - } - function g5() { - return !c || x; - } - function g6() { - return !!c && x; - } - function g7() { - return !!c || x; - } - function g8() { - return !c && x; - } - `); - expect(transform(source)).toBe(expected); - }); - - // From UglifyJS - it("should simplify logical expression of the following forms of &&", () => { - // compress to right - let sources = unpad( - ` - a = true && foo - a = 1 && console.log("asdf") - a = 4 * 2 && foo() - a = 10 == 10 && foo() + bar() - a = "foo" && foo() - a = 1 + "a" && foo / 10 - a = -1 && 5 << foo - a = 6 && 10 - a = !NaN && foo() - ` - ).split("\n"); - - let expected = unpad( - ` - a = foo; - a = console.log("asdf"); - a = foo(); - a = foo() + bar(); - a = foo(); - a = foo / 10; - a = 5 << foo; - a = 10; - a = foo(); - ` - ).split("\n"); - - expect(sources.map(s => transform(s))).toEqual(expected); - - // compress to left - sources = unpad( - ` - a = false && bar - a = NaN && console.log("a") - a = 0 && bar() - a = undefined && foo(bar) - a = 3 * 3 - 9 && bar(foo) - a = 9 == 10 && foo() - a = !"string" && foo % bar - a = 0 && 7 - ` - ).split("\n"); - - expected = unpad( - ` - a = false; - a = NaN; - a = 0; - a = undefined; - a = 0; - a = false; - a = false; - a = 0; - ` - ).split("\n"); - - expect(sources.map(s => transform(s))).toEqual(expected); - - // don't compress - sources = unpad( - ` - a = foo() && true; - a = console.log && 3 + 8; - a = foo + bar + 5 && "a"; - a = 4 << foo && -1.5; - a = bar() && false; - a = foo() && 0; - a = bar() && NaN; - a = foo() && null; - ` - ).split("\n"); - - expect(sources.map(s => transform(s))).toEqual(sources); - }); - - it("should simplify logical expression of the following forms of ||", () => { - // compress to left - let sources = unpad( - ` - a = true || condition; - a = 1 || console.log("a"); - a = 2 * 3 || 2 * condition; - a = 5 == 5 || condition + 3; - a = "string" || 4 - condition; - a = 5 + "" || condition / 5; - a = -4.5 || 6 << condition; - a = 6 || 7; - ` - ).split("\n"); - - let expected = unpad( - ` - a = true; - a = 1; - a = 6; - a = true; - a = "string"; - a = "5"; - a = -4.5; - a = 6; - ` - ).split("\n"); - - expect(sources.map(s => transform(s))).toEqual(expected); - - sources = unpad( - ` - a = false || condition; - a = 0 || console.log("b"); - a = NaN || console.log("c"); - a = undefined || 2 * condition; - a = null || condition + 3; - a = 2 * 3 - 6 || 4 - condition; - a = 10 == 7 || condition / 5; - a = !"string" || 6 % condition; - a = null || 7; - ` - ).split("\n"); - - expected = unpad( - ` - a = condition; - a = console.log("b"); - a = console.log("c"); - a = 2 * condition; - a = condition + 3; - a = 4 - condition; - a = condition / 5; - a = 6 % condition; - a = 7; - ` - ).split("\n"); - - expect(sources.map(s => transform(s))).toEqual(expected); - - // don't compress - sources = unpad( - ` - a = condition || true; - a = console.log("a") || 2; - a = 4 - condition || "string"; - a = 6 << condition || -4.5; - a = condition || false; - a = console.log("b") || NaN; - a = console.log("c") || 0; - a = 2 * condition || undefined; - a = condition + 3 || null; - ` - ).split("\n"); - - expect(sources.map(s => transform(s))).toEqual(sources); - }); - - it("should transform complex logical expressions", () => { - const sources = unpad( - ` - a = true && 1 && foo - a = 1 && 4 * 2 && console.log("asdf") - a = 4 * 2 && NaN && foo() - a = 10 == 11 || undefined && foo() + bar() && bar() - a = -1 && undefined || 5 << foo - ` - ).split("\n"); - - const expected = unpad( - ` - a = foo; - a = console.log("asdf"); - a = NaN; - a = undefined; - a = 5 << foo; - ` - ).split("\n"); - - expect(sources.map(s => transform(s))).toEqual(expected); - }); - - // https://github.com/babel/babili/issues/115 - it("should transform impure conditional statements correctly - issue#115", () => { - const source = unpad(` - (function () { - a = x ? true : false; - c = 1 ? (this.get(x), a = b, true) : (foo.bar, false); - })(); - `); - const expected = unpad(` - (function () { - a = !!x, c = 1 ? (this.get(x), a = b, true) : (foo.bar, false); - })(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should require block for single block scoped declaration in if/else", () => { - const source = unpad(` - if (false) { - let { a } = foo(); - } else if (true) { - const x = bar(); - } else { - function baz() {} - } - `); - const expected = source; - expect(transform(source)).toBe(expected); - }); - - 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 not simplify assignments when it is not an equal operator", () => { - 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 + 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; - ` - ).replace(/\s+/g, " "); - - expect(transform(source)).toBe(expected); - }); - - it("should not simplify assignments further when it is not an equal operator", () => { - const source = unpad(` - x = x + (x >> 1), - x = x - (x >> 1), - x = x * (x >> 1), - x = x % (x >> 1), - x = x << (x >> 1), - x = x >> (x >> 1), - x = x >>> (x >> 1), - x = x & (x >> 1), - x = x | (x >> 1), - x = x ^ (x >> 1), - x = x / (x >> 1), - x = x ** (x >> 1); - `); - const expected = 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; - ` - ).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, - foo[null] = foo[null] + 1, - foo[undefined] = foo[undefined] + 1, - foo.bar = foo.bar || {}; - `); - // TODO: foo[void 0] = foo[void 0] + 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, - ++foo[null], - ++foo[undefined], - foo.bar = foo.bar || {}; - ` - ).replace(/\s+/g, " "); - - expect(transform(source)).toBe(expected); - }); - - it("should simplify assignments w. super", () => { - const source = unpad(` - class Foo { - foo() { - super.foo = super.foo + 1; - } - }; - `); - const expected = unpad(` - class Foo { - foo() { - ++super.foo; - } - }; - `); - - expect(transform(source)).toBe(expected); - }); + const b = 1; + return "doesn't matter if this is reached or not"; + } + `, + ` + function foo() { + if (a) return x ? void 0 : x; + const b = 1; + return "doesn't matter if this is reached or not"; + } + ` + ); - it("should not simplify assignments w. template literals", () => { - const source = unpad("foo[`x`] = foo[`x`] + 1;"); + thePlugin( + "should fix issue#281 with if..return", + ` + function foo() { + if (x) + return; + function bar() {} + bar(a); + } + `, + ` + function foo() { + function bar() {} + x || bar(a); + } + ` + ); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should fix issue#323 with != and !==", + ` + function foo() { + var x, y; + y = o[x]; + foo(y !== undefined); + } + `, + ` + function foo() { + var x, y; + y = o[x], foo(y !== undefined); + } + `, + { + plugins: [plugin, comparisonPlugin] + } + ); - it("should consider hoisted definitions in if_return", () => { - const source = unpad(` - function foo() { - bar(); - if(x) return; - const {a}=b; - function bar () { - baz(); - bar(); - } + thePlugin( + "should fix issue#423 with fallthrough in default case", + ` + function foo(bar) { + switch (bar) { + case 'a': + return 1; + case 'b': + default: + return 4; + case 'c': + return 3; } - `); - // TODO: - // Fix indenting - const expected = unpad(` - function foo() { - function bar() { - baz(), bar(); - } + } + `, + ` + function foo(bar) { + return bar === 'a' ? 1 : bar === 'c' ? 3 : 4; + } + ` + ); - if (bar(), !x) { - const { a } = b; - } + thePlugin( + "should convert multiple fallthrough in switch to conditional expression", + ` + function foo(bar) { + switch (bar) { + case 'a': + case 'b': + return 1; + case 'd': + default: + return 4; + case 'c': + return 3; } - `); - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function foo(bar) { + return bar === 'a' || bar === 'b' ? 1 : bar === 'c' ? 3 : 4; + } + ` + ); - it("should optimize if..else..returns", () => { - const source = unpad(` - function foo() { - if (a) { - if (x) return; - else return x; - } - const b = 1; - return "doesn't matter if this is reached or not"; - } - `); - const expected = unpad(` - function foo() { - if (a) return x ? void 0 : x; - const b = 1; - return "doesn't matter if this is reached or not"; - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should fix issue#281 with if..return", () => { - const source = unpad(` - function foo() { - if (x) - return; - function bar() {} - bar(a); - } - `); - const expected = unpad(` - function foo() { - function bar() {} - x || bar(a); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should fix issue#323 with != and !==", () => { - const source = unpad(` - function foo() { - var x, y; - y = o[x]; - foo(y !== undefined); - } - `); - const expected = unpad(` - function foo() { - var x, y; - y = o[x], foo(y !== undefined); - } - `); - function transform(code) { - return babel.transform(code, { - plugins: [plugin, comparisonPlugin] - }).code; - } - expect(transform(source)).toBe(expected); - }); - - it("should fix issue#423 with fallthrough in default case", () => { - const source = unpad(` - function foo(bar) { - switch (bar) { - case 'a': - return 1; - case 'b': - default: - return 4; - case 'c': - return 3; - } - } - `); - const expected = unpad(` - function foo(bar) { - return bar === 'a' ? 1 : bar === 'c' ? 3 : 4; - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should convert multiple fallthrough in switch to conditional expression", () => { - const source = unpad(` - function foo(bar) { - switch (bar) { - case 'a': - case 'b': - return 1; - case 'd': - default: - return 4; - case 'c': - return 3; + thePlugin( + "should fix#455 and deopt when scope tree is not updated", + ` + function foo(param) { + if (param === null) return; + let thingA = param.a; + let thingB = param.b; + if (!thingA && !thingB) return; + let thingC = param.c; + } + `, + ` + function foo(param) { + if (param !== null) { + let thingA = param.a; + let thingB = param.b; + if (thingA || thingB) { + let thingC = param.c; + } } - } - `); - const expected = unpad(` - function foo(bar) { - return bar === 'a' || bar === 'b' ? 1 : bar === 'c' ? 3 : 4; - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should fix#455 and deopt when scope tree is not updated", () => { - const source = unpad(` - function foo(param) { - if (param === null) return; - let thingA = param.a; - let thingB = param.b; - if (!thingA && !thingB) return; - let thingC = param.c; - } - `); - const expected = unpad(` - function foo(param) { - if (param !== null) { - let thingA = param.a; - let thingB = param.b; - if (thingA || thingB) { - let thingC = param.c; - } - } - } - `); - expect(transform(source)).toBe(expected); - }); + } + ` + ); }); diff --git a/packages/babel-plugin-minify-type-constructors/__tests__/type-constructors-test.js b/packages/babel-plugin-minify-type-constructors/__tests__/type-constructors-test.js index 5466198fc..d44d22c23 100644 --- a/packages/babel-plugin-minify-type-constructors/__tests__/type-constructors-test.js +++ b/packages/babel-plugin-minify-type-constructors/__tests__/type-constructors-test.js @@ -3,234 +3,267 @@ jest.autoMockOff(); const babel = require("babel-core"); const plugin = require("../src/index"); const unpad = require("../../../utils/unpad"); - -function transform(code, opts = {}) { - return babel.transform(code, { - plugins: [[plugin, opts]] - }).code; -} +const thePlugin = require("../../../utils/test-transform")(plugin); describe("type-constructors-plugin", () => { - it("should turn Boolean(x) to !!x", () => { - const source = "Boolean(x);"; - const expected = "!!x;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn Boolean(x) to !!x", + ` + Boolean(x); + `, + ` + !!x; + ` + ); - it("should turn Number(x) to +x", () => { - const source = "Number(x);"; - const expected = "+x;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn Number(x) to +x", + ` + Number(x); + `, + ` + +x; + ` + ); - it("should turn String(x) to x + ''", () => { - const source = "String(x);"; - const expected = 'x + "";'; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn String(x) to x + ''", + ` + String(x); + `, + ` + x + ""; + ` + ); - it("should turn Array() to []", () => { - const source = "Array();"; - const expected = "[];"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn Array() to []", + ` + Array(); + `, + ` + []; + ` + ); - it("should turn new Array() to []", () => { - const source = "new Array();"; - const expected = "[];"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn new Array() to []", + ` + new Array(); + `, + ` + []; + ` + ); - it("should turn Array(nonNumericValue) to [nonNumericValue]", () => { - const source = unpad(` - Array("Rome"); - Array(false); - Array(null); - new Array({}); - new Array([a, b]); - Array([]); - Array(t); - new Array(a.b); - new Array((() => 5)()); - `); - const expected = unpad(` - ["Rome"]; - [false]; - [null]; - [{}]; - [[a, b]]; - [[]]; - Array(t); - Array(a.b); - Array((() => 5)()); - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn Array(nonNumericValue) to [nonNumericValue]", + ` + Array("Rome"); + Array(false); + Array(null); + new Array({}); + new Array([a, b]); + Array([]); + Array(t); + new Array(a.b); + new Array((() => 5)()); + `, + ` + ["Rome"]; + [false]; + [null]; + [{}]; + [[a, b]]; + [[]]; + Array(t); + Array(a.b); + Array((() => 5)()); + ` + ); - it("should turn Array(number) to [,] only if number is <=6", () => { - const source = unpad(` - Array(0); - Array(1); - Array(2 + 4); - Array(7); - `); - const expected = unpad(` - []; - [,]; - [,,,,,,]; - Array(7); - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn Array(number) to [,] only if number is <=6", + ` + Array(0); + Array(1); + Array(2 + 4); + Array(7); + `, + ` + []; + [,]; + [,,,,,,]; + Array(7); + ` + ); - it("should turn new Array(number) to Array(number) if number is >6", () => { - const source = unpad(` - new Array(6); - new Array(7); - `); - const expected = unpad(` - [,,,,,,]; - Array(7); - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn new Array(number) to Array(number) if number is >6", + ` + new Array(6); + new Array(7); + `, + ` + [,,,,,,]; + Array(7); + ` + ); - it("should turn Array(value, value) to [value, value]", () => { - const source = unpad(` - Array("a", "b"); - new Array("0", "1", {}); - Array(10, Symbol(), foo()); - `); - const expected = unpad(` - ["a", "b"]; - ["0", "1", {}]; - [10, Symbol(), foo()]; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn Array(value, value) to [value, value]", + ` + Array("a", "b"); + new Array("0", "1", {}); + Array(10, Symbol(), foo()); + `, + ` + ["a", "b"]; + ["0", "1", {}]; + [10, Symbol(), foo()]; + ` + ); - it("should turn Object() to {}", () => { - const source = "var x = Object();"; - const expected = "var x = {};"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn Object() to {}", + ` + var x = Object(); + `, + ` + var x = {}; + ` + ); - it("should turn new Object() to {}", () => { - const source = "var x = new Object();"; - const expected = "var x = {};"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn new Object() to {}", + ` + var x = new Object(); + `, + ` + var x = {}; + ` + ); - it("should change Object(null|undefined) to {}", () => { - const source = unpad(` - [ - Object(null), - Object(undefined), - new Object(void 0) - ] - `); - const expected = "[{}, {}, {}];"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should change Object(null|undefined) to {}", + ` + [ + Object(null), + Object(undefined), + new Object(void 0) + ] + `, + ` + [{}, {}, {}]; + ` + ); - it("should change Object({a:b}) to {a:b}", () => { - const source = unpad(` - [ - Object({}), - Object({a:b}), - Object({a:b, c:d}), - ] - `); // todo: add Object(Array()) - const expected = "[{}, { a: b }, { a: b, c: d }];"; - expect(transform(source)).toBe(expected); - }); + // TODO: add Object(Array()) + thePlugin( + "should change Object({a:b}) to {a:b}", + ` + [ + Object({}), + Object({a:b}), + Object({a:b, c:d}), + ] + `, + ` + [{}, { a: b }, { a: b, c: d }]; + ` + ); - it("should change Object([]) to []", () => { - const source = unpad(` - [ - Object([]), - Object([1]), - Object([1,2]), - new Object([null]) - ] - `); // todo: add Object(Array()) - const expected = "[[], [1], [1, 2], [null]];"; - expect(transform(source)).toBe(expected); - }); + // TODO: add Object(Array()) + thePlugin( + "should change Object([]) to []", + ` + [ + Object([]), + Object([1]), + Object([1,2]), + new Object([null]) + ] + `, + ` + [[], [1], [1, 2], [null]]; + ` + ); - it("should change Object(localFn) to localFn", () => { - const source = unpad(` - function a() {}; - [ - Object(function () {}), - new Object(a), - Object(Array) - ] - `); - const expected = unpad(` - function a() {}; - [function () {}, a, Object(Array)]; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should change Object(localFn) to localFn", + ` + function a() {}; + [ + Object(function () {}), + new Object(a), + Object(Array) + ] + `, + ` + function a() {}; + [function () {}, a, Object(Array)]; + ` + ); - it("shouldn't change Object(value) for unrecognized values", () => { - const source = unpad(` - [ - Object("undefined"), - Object(nulled), - Object(0), - Object(false), - Object(stuff()) - ] - `); - const expected = - '[Object("undefined"), Object(nulled), Object(0), Object(false), Object(stuff())];'; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "shouldn't change Object(value) for unrecognized values", + ` + [ + Object("undefined"), + Object(nulled), + Object(0), + Object(false), + Object(stuff()) + ] + `, + ` + [Object("undefined"), Object(nulled), Object(0), Object(false), Object(stuff())]; + ` + ); - it("should change new Object(value) to Object(value) for unrecognized values", () => { - const source = unpad(` - [ - new Object("function"), - new Object(Symbol), - new Object(true), - new Object(1), - new Object(call({ me: true })) - ] - `); - const expected = - '[Object("function"), Object(Symbol), Object(true), Object(1), Object(call({ me: true }))];'; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should change new Object(value) to Object(value) for unrecognized values", + ` + [ + new Object("function"), + new Object(Symbol), + new Object(true), + new Object(1), + new Object(call({ me: true })) + ] + `, + ` + [Object("function"), Object(Symbol), Object(true), Object(1), Object(call({ me: true }))]; + ` + ); - it("should change Object() to ({}) in ambiguous contexts", () => { - const source = unpad(` - new Object(); - var foo = () => Object(); - var bar = () => Object({ baz: 3 }); - `); - const expected = unpad(` - ({}); - var foo = () => ({}); - var bar = () => ({ baz: 3 }); - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should change Object() to ({}) in ambiguous contexts", + ` + new Object(); + var foo = () => Object(); + var bar = () => Object({ baz: 3 }); + `, + ` + ({}); + var foo = () => ({}); + var bar = () => ({ baz: 3 }); + ` + ); - it("shouldn't change referenced identifiers", () => { - const source = unpad(` - (function (Boolean, String, Number, Array, Object) { - return Boolean(a), String(b), Number(c), Array(d), Object(d); - })(MyBoolean, MyString, MyNumber, MyArray, MyObject); - `); - const expected = unpad(` - (function (Boolean, String, Number, Array, Object) { - return Boolean(a), String(b), Number(c), Array(d), Object(d); - })(MyBoolean, MyString, MyNumber, MyArray, MyObject); - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "shouldn't change referenced identifiers", + ` + (function (Boolean, String, Number, Array, Object) { + return Boolean(a), String(b), Number(c), Array(d), Object(d); + })(MyBoolean, MyString, MyNumber, MyArray, MyObject); + `, + ` + (function (Boolean, String, Number, Array, Object) { + return Boolean(a), String(b), Number(c), Array(d), Object(d); + })(MyBoolean, MyString, MyNumber, MyArray, MyObject); + ` + ); // options tests it("should not transform type for falsy option", () => { @@ -252,21 +285,24 @@ describe("type-constructors-plugin", () => { })(); ` ); - const expected = source; - expect(transform(source, { [names[i]]: false })).toBe(expected); + expect( + babel.transform(source, { + plugins: [[plugin, { [names[i]]: false }]] + }).code + ).toBe(source); } }); // https://github.com/babel/babili/issues/206 - it("should handle floating point numbers in Array()", () => { - const source = unpad(` - new Array(-0.01); - new Array(-1); - `); - const expected = unpad(` - Array(-0.01); - Array(-1); - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should handle floating point numbers in Array()", + ` + new Array(-0.01); + new Array(-1); + `, + ` + Array(-0.01); + Array(-1); + ` + ); }); diff --git a/packages/babel-plugin-transform-inline-consecutive-adds/__tests__/transform-inline-consecutive-adds-test.js b/packages/babel-plugin-transform-inline-consecutive-adds/__tests__/transform-inline-consecutive-adds-test.js index 6e9d31fa0..5da120d02 100644 --- a/packages/babel-plugin-transform-inline-consecutive-adds/__tests__/transform-inline-consecutive-adds-test.js +++ b/packages/babel-plugin-transform-inline-consecutive-adds/__tests__/transform-inline-consecutive-adds-test.js @@ -1,332 +1,326 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const unpad = require("../../../utils/unpad"); -const plugin = require("../src/index"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("transform-inline-consecutive-adds-plugin", () => { - it("should collapse simple consecutive", () => { - const source = unpad(` - const foo = { - z: 3.0 - }; - foo.a = 42; - foo.b = ["hi"]; - foo.c = bar(); - foo.d = "str"; - `); - const expected = unpad(` - const foo = { - z: 3.0, - a: 42, - b: ["hi"], - c: bar(), - d: "str" - }; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should collapse simple consecutive", + ` + const foo = { + z: 3.0 + }; + foo.a = 42; + foo.b = ["hi"]; + foo.c = bar(); + foo.d = "str"; + `, + ` + const foo = { + z: 3.0, + a: 42, + b: ["hi"], + c: bar(), + d: "str" + }; + ` + ); - it("should collapse only up to last ExpressionStatement", () => { - const source = unpad(` - const foo = {}; - foo.a = 42; - console.log(foo); - `); - const expected = unpad(` - const foo = { - a: 42 - }; + thePlugin( + "should collapse only up to last ExpressionStatement", + ` + const foo = {}; + foo.a = 42; + console.log(foo); + `, + ` + const foo = { + a: 42 + }; - console.log(foo); - `); - expect(transform(source)).toBe(expected); - }); + console.log(foo); + ` + ); - it("should not collapse if lval is nested MemberExpression", () => { - const source = unpad(` - const foo = {}; - foo.bar.a = 42; - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse if lval is nested MemberExpression", + ` + const foo = {}; + foo.bar.a = 42; + ` + ); - it("should not collapse if lval has wrong name", () => { - const source = unpad(` - const foo = {}; - bar.a = 42; - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse if lval has wrong name", + ` + const foo = {}; + bar.a = 42; + ` + ); - it("should not collapse if has direct dependency issues", () => { - const source = unpad(` - const foo = {}; - foo.a = function () { + thePlugin( + "should not collapse if has direct dependency issues", + ` + const foo = {}; + foo.a = function () { + console.log(3); + }; + foo.b = foo.a(); + `, + ` + const foo = { + a: function () { console.log(3); - }; - foo.b = foo.a(); - `); - const expected = unpad(` - const foo = { - a: function () { - console.log(3); - } - }; + } + }; - foo.b = foo.a(); - `); - expect(transform(source)).toBe(expected); - }); + foo.b = foo.a(); + ` + ); - it("should not collapse if has indirect dependency issues", () => { - const source = unpad(` - var foo = {}; - foo.a = 4; - foo.b = cat(); - function cat() { - return bar(); - } + thePlugin( + "should not collapse if has indirect dependency issues", + ` + var foo = {}; + foo.a = 4; + foo.b = cat(); + function cat() { + return bar(); + } + function bar() { + console.log(foo); + return 0; + } + `, + ` + var foo = { + a: 4 + }; + + foo.b = cat(); + function cat() { + return bar(); + } + function bar() { + console.log(foo); + return 0; + } + ` + ); + + thePlugin( + "should not collapse if has indirect, nested dependency issues", + ` + var foo = {}; + foo.a = 4; + foo.b = cat(); + function cat() { + return bar(); function bar() { console.log(foo); return 0; } - `); - const expected = unpad(` - var foo = { - a: 4 - }; + } + `, + ` + var foo = { + a: 4 + }; - foo.b = cat(); - function cat() { - return bar(); - } + foo.b = cat(); + function cat() { + return bar(); function bar() { console.log(foo); return 0; } - `); - expect(transform(source)).toBe(expected); - }); - - it("should not collapse if has indirect, nested dependency issues", () => { - const source = unpad(` - var foo = {}; - foo.a = 4; - foo.b = cat(); - function cat() { - return bar(); - function bar() { - console.log(foo); - return 0; - } - } - `); - const expected = unpad(` - var foo = { - a: 4 - }; + } + ` + ); - foo.b = cat(); - function cat() { - return bar(); - function bar() { - console.log(foo); - return 0; - } - } - `); - expect(transform(source)).toBe(expected); - }); - - it("should collapse computed properties if they are literals", () => { - const source = unpad(` - var foo = {}; - foo["a"] = 0; - foo[4] = 1; - `); - const expected = unpad(` - var foo = { - "a": 0, - 4: 1 - }; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should collapse computed properties if they are literals", + ` + var foo = {}; + foo["a"] = 0; + foo[4] = 1; + `, + ` + var foo = { + "a": 0, + 4: 1 + }; + ` + ); - it("should not collapse computed properties otherwise", () => { - const source = unpad(` - var foo = {}; - foo[global] = 0; - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse computed properties otherwise", + ` + var foo = {}; + foo[global] = 0; + ` + ); - it("should not collapse computed properties with dependency issues", () => { - const source = unpad(` - var foo = {}; - foo[bar()] = 0; - function bar() { - console.log(foo); - return 0; - } - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse computed properties with dependency issues", + ` + var foo = {}; + foo[bar()] = 0; + function bar() { + console.log(foo); + return 0; + } + ` + ); - it("should not collapse computed properties with circular reference", () => { - const source = unpad(` - var foo = {}; - foo.bar = foo; - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse computed properties with circular reference", + ` + var foo = {}; + foo.bar = foo; + ` + ); - it("should collapse statements with multiple assignments", () => { - const source = unpad(` - var foo = {}; - foo.a = 0, foo.b = 2; - `); - const expected = unpad(` - var foo = { - a: 0, - b: 2 - }; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should collapse statements with multiple assignments", + ` + var foo = {}; + foo.a = 0, foo.b = 2; + `, + ` + var foo = { + a: 0, + b: 2 + }; + ` + ); - it("should not collapse statements with multiple assignments and dependency issues", () => { - const source = unpad(` - var foo = {}; - foo.a = 0, foo.b = bar(); - function bar() { - console.log(foo); - return 0; - } - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse statements with multiple assignments and dependency issues", + ` + var foo = {}; + foo.a = 0, foo.b = bar(); + function bar() { + console.log(foo); + return 0; + } + ` + ); - it("should collapse statements for arrays", () => { - const source = unpad(` - var foo = [1, 2]; - foo.push(3, 4), foo.push(5); - foo.push(6); - `); - const expected = unpad(` - var foo = [1, 2, 3, 4, 5, 6]; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should collapse statements for arrays", + ` + var foo = [1, 2]; + foo.push(3, 4), foo.push(5); + foo.push(6); + `, + ` + var foo = [1, 2, 3, 4, 5, 6]; + ` + ); - it("should collapse statements for sets", () => { - const source = unpad(` - var foo = new Set(); - foo.add(1), foo.add(2); - foo.add(3); - `); - const expected = unpad(` - var foo = new Set([1, 2, 3]); - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should collapse statements for sets", + ` + var foo = new Set(); + foo.add(1), foo.add(2); + foo.add(3); + `, + ` + var foo = new Set([1, 2, 3]); + ` + ); - it("should collapse statements for array-initialized sets", () => { - const source = unpad(` - var foo = new Set([1, 2]); - foo.add(3); - `); - const expected = unpad(` - var foo = new Set([1, 2, 3]); - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should collapse statements for array-initialized sets", + ` + var foo = new Set([1, 2]); + foo.add(3); + `, + ` + var foo = new Set([1, 2, 3]); + ` + ); - it("should not collapse statements for array-initialized sets with circular reference", () => { - const source = unpad(` - var foo = new Set([1, 2]); - foo.add(foo); - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse statements for array-initialized sets with circular reference", + ` + var foo = new Set([1, 2]); + foo.add(foo); + ` + ); - it("should collapse array property assignments", () => { - const source = unpad(` - var foo = []; - foo[5] = 'blah'; - foo[3] = 'blah'; - foo[7] = 'blah'; - `); - const expected = unpad(` - var foo = [,,, 'blah',, 'blah',, 'blah']; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should collapse array property assignments", + ` + var foo = []; + foo[5] = 'blah'; + foo[3] = 'blah'; + foo[7] = 'blah'; + `, + ` + var foo = [,,, 'blah',, 'blah',, 'blah']; + ` + ); - it("should not collapse array property assignments if long", () => { - const source = unpad(` - var foo = []; - foo[10] = 'blah'; - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse array property assignments if long", + ` + var foo = []; + foo[10] = 'blah'; + ` + ); - it("should not collapse array property assignments if override initial", () => { - const source = unpad(` - var foo = [1, 2, 3]; - foo[2] = 'blah'; - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse array property assignments if override initial", + ` + var foo = [1, 2, 3]; + foo[2] = 'blah'; + ` + ); - it("should not collapse array property assignments if override dynamic", () => { - const source = unpad(` - var foo = [1, 2]; - foo[2] = 'blah'; - foo[2] = 'ok'; - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse array property assignments if override dynamic", + ` + var foo = [1, 2]; + foo[2] = 'blah'; + foo[2] = 'ok'; + ` + ); - it("should not collapse array property assignments if index is float", () => { - const source = unpad(` - var foo = []; - foo[2.1] = 'blah'; - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse array property assignments if index is float", + ` + var foo = []; + foo[2.1] = 'blah'; + ` + ); - it("should not collapse array property assignments if index is non-int as string", () => { - const source = unpad(` - var foo = []; - foo['2.1'] = 'blah'; - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse array property assignments if index is non-int as string", + ` + var foo = []; + foo['2.1'] = 'blah'; + ` + ); - it("should collapse array property assignments if index is int as string", () => { - const source = unpad(` - var foo = []; - foo['2'] = 'blah'; - `); - const expected = unpad(` - var foo = [,, 'blah']; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should collapse array property assignments if index is int as string", + ` + var foo = []; + foo['2'] = 'blah'; + `, + ` + var foo = [,, 'blah']; + ` + ); - it("should not collapse array property assignments if it is circular reference", () => { - const source = unpad(` - var foo = []; - foo[2] = foo; - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not collapse array property assignments if it is circular reference", + ` + var foo = []; + foo[2] = foo; + ` + ); }); diff --git a/packages/babel-plugin-transform-inline-environment-variables/__tests__/inline-env-var-test.js b/packages/babel-plugin-transform-inline-environment-variables/__tests__/inline-env-var-test.js index 25b617a87..76b020b81 100644 --- a/packages/babel-plugin-transform-inline-environment-variables/__tests__/inline-env-var-test.js +++ b/packages/babel-plugin-transform-inline-environment-variables/__tests__/inline-env-var-test.js @@ -1,23 +1,27 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("inline-env-plugin", () => { - it("should inline environment variables", () => { - const prev = process.env.NODE_ENV; + let prev; + beforeAll(() => { + prev = process.env.NODE_ENV; process.env.NODE_ENV = "development"; + }); - const source = "process.env.NODE_ENV"; - const expected = '"development";'; - expect(transform(source)).toBe(expected); + thePlugin( + "should inline environment variables", + ` + process.env.NODE_ENV + `, + ` + "development"; + ` + ); + afterAll(() => { process.env.NODE_ENV = prev; }); }); diff --git a/packages/babel-plugin-transform-member-expression-literals/__tests__/transform-member-expression-literals-test.js b/packages/babel-plugin-transform-member-expression-literals/__tests__/transform-member-expression-literals-test.js index 2b878b4aa..21d468597 100644 --- a/packages/babel-plugin-transform-member-expression-literals/__tests__/transform-member-expression-literals-test.js +++ b/packages/babel-plugin-transform-member-expression-literals/__tests__/transform-member-expression-literals-test.js @@ -1,48 +1,56 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); -const unpad = require("../../../utils/unpad"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("transform-member-expressions-literals-plugin", () => { - it("should work with string literals", () => { - const source = "foo['bar'];"; - const expected = "foo.bar;"; - expect(transform(source)).toBe(expected); - }); - - it("should work with numbers", () => { - const source = "foo['1'];"; - const expected = "foo[1];"; - expect(transform(source)).toBe(expected); - }); - - it("should not strip necessaary quotes for numeric like things", () => { - const source = "data['00'] = 5;"; - expect(transform(source)).toBe(source); - }); - - it("should not transform invalid identifiers", () => { - const source = unpad(` + thePlugin( + "should work with string literals", + ` + foo['bar']; + `, + ` + foo.bar; + ` + ); + + thePlugin( + "should work with numbers", + ` + foo['1']; + `, + ` + foo[1]; + ` + ); + + thePlugin( + "should not strip necessaary quotes for numeric like things", + ` + data['00'] = 5; + ` + ); + + thePlugin( + "should not transform invalid identifiers", + ` foo["default"]; foo["import"]; - `); - expect(transform(source)).toBe(source); - }); - - it("should not transform non-string properties", () => { - const source = "foo[a];"; - expect(transform(source)).toBe(source); - }); - - it("should not transform literals that are not computed", () => { - const source = "foo.bar;"; - expect(transform(source)).toBe(source); - }); + ` + ); + + thePlugin( + "should not transform non-string properties", + ` + foo[a]; + ` + ); + + thePlugin( + "should not transform literals that are not computed", + ` + foo.bar; + ` + ); }); diff --git a/packages/babel-plugin-transform-merge-sibling-variables/__tests__/transform-merge-sibling-variables-test.js b/packages/babel-plugin-transform-merge-sibling-variables/__tests__/transform-merge-sibling-variables-test.js index adb8af4bc..53e459b28 100644 --- a/packages/babel-plugin-transform-merge-sibling-variables/__tests__/transform-merge-sibling-variables-test.js +++ b/packages/babel-plugin-transform-merge-sibling-variables/__tests__/transform-merge-sibling-variables-test.js @@ -1,165 +1,147 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); -const unpad = require("../../../utils/unpad"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("transform-merge-sibling-variables-plugin", () => { - it("concat vars", () => { - const source = unpad(` + thePlugin( + "concat vars", + ` + var i = 0; + var x = 0; + var y = 0; + `, + ` + var i = 0, + x = 0, + y = 0; + ` + ); + + thePlugin( + "concat vars in for loops", + ` + var i = 0; + var j = 0; + for (var x = 0; x < 10; x++) console.log(i + x); + `, + ` + for (var i = 0, j = 0, x = 0; x < 10; x++) console.log(i + x); + ` + ); + + thePlugin( + "don't concat block-scoped variables in for loops", + ` + let i = 0; + for (let x = 0; x < 10; x++) console.log(i + x); + ` + ); + + thePlugin( + "don't concat constants in for loops", + ` + const j = 0; + for (const x = 0;;) console.log(j + x); + ` + ); + + thePlugin( + "concat block-scoped vars next to, but not into for loops", + ` + let i = 0; + let y = 0; + for (let x = 0; x < 10; x++) console.log(i + x); + `, + ` + let i = 0, + y = 0; + + for (let x = 0; x < 10; x++) console.log(i + x); + ` + ); + + thePlugin( + "lift var declarations to loop intializer", + ` + for (var i = 0; i < 0; i++) { + var j = jj(); + } + for (var i=0;;) var j = 0; + `, + ` + for (var i = 0, j; i < 0; i++) { + j = jj(); + } + for (var i = 0, j;;) j = 0; + ` + ); + + thePlugin( + "lift let declarations to loop intializer", + ` + for (let i = 0; i < 0; i++) { + let j = jj(); + } + `, + ` + for (let i = 0, j; i < 0; i++) { + j = jj(); + } + ` + ); + + thePlugin( + "dont lift declarations on object/array pattern", + ` + for (var i = 0; i < 0; i++) { + var [j] = jj(); + } + for (var i = 0; i < 0; i++) { + var { j } = jj(); + } + ` + ); + + thePlugin( + "dont lift declarations when no body is present", + ` + for (;;) {} + for (;;) var i = 0; + ` + ); + + thePlugin( + "dont lift when the declarations are of different kind", + ` + for (let i = 0; i < 0; i++) { var i = 0; - var x = 0; - var y = 0; - `); - const expected = unpad(` + } + ` + ); + + thePlugin( + "dont lift when the declarations are not initialized", + ` + for (var i = 0;;) { + var i; + } + ` + ); + + thePlugin( + "dont lift when there are multiple declarations", + ` + for (var i = 0; i < 0; i++) { + var i = 0, k = 0; + } + `, + ` + for (var i = 0; i < 0; i++) { var i = 0, - x = 0, - y = 0; - `); - - expect(transform(source)).toBe(expected); - }); - - it("concat vars in for loops", () => { - const source = unpad(` - var i = 0; - var j = 0; - for (var x = 0; x < 10; x++) console.log(i + x); - `); - const expected = - "for (var i = 0, j = 0, x = 0; x < 10; x++) console.log(i + x);"; - - expect(transform(source).trim()).toBe(expected); - }); - - it("don't concat block-scoped variables in for loops", () => { - const source = unpad(` - let i = 0; - for (let x = 0; x < 10; x++) console.log(i + x); - `); - - expect(transform(source)).toBe(source); - }); - - it("don't concat constants in for loops", () => { - const source = unpad(` - const j = 0; - for (const x = 0;;) console.log(j + x); - `); - - expect(transform(source)).toBe(source); - }); - - it("concat block-scoped vars next to, but not into for loops", () => { - const source = unpad(` - let i = 0; - let y = 0; - for (let x = 0; x < 10; x++) console.log(i + x); - `); - const expected = unpad(` - let i = 0, - y = 0; - - for (let x = 0; x < 10; x++) console.log(i + x); - `); - - expect(transform(source)).toBe(expected); - }); - - it("lift var declarations to loop intializer", () => { - const source = unpad(` - for (var i = 0; i < 0; i++) { - var j = jj(); - } - for (var i=0;;) var j = 0; - `); - const expected = unpad(` - for (var i = 0, j; i < 0; i++) { - j = jj(); - } - for (var i = 0, j;;) j = 0; - `); - - expect(transform(source)).toBe(expected); - }); - - it("lift let declarations to loop intializer", () => { - const source = unpad(` - for (let i = 0; i < 0; i++) { - let j = jj(); - } - `); - const expected = unpad(` - for (let i = 0, j; i < 0; i++) { - j = jj(); - } - `); - - expect(transform(source)).toBe(expected); - }); - - it("dont lift declarations on object/array pattern", () => { - const source = unpad(` - for (var i = 0; i < 0; i++) { - var [j] = jj(); - } - for (var i = 0; i < 0; i++) { - var { j } = jj(); - } - `); - - expect(transform(source)).toBe(source); - }); - - it("dont lift declarations when no body is present", () => { - const source = unpad(` - for (;;) {} - for (;;) var i = 0; - `); - - expect(transform(source)).toBe(source); - }); - - it("dont lift when the declarations are of different kind", () => { - const source = unpad(` - for (let i = 0; i < 0; i++) { - var i = 0; - } - `); - - expect(transform(source)).toBe(source); - }); - - it("dont lift when the declarations are not initialized", () => { - const source = unpad(` - for (var i = 0;;) { - var i; - } - `); - - expect(transform(source)).toBe(source); - }); - - it("dont lift when there are multiple declarations", () => { - const source = unpad(` - for (var i = 0; i < 0; i++) { - var i = 0, k = 0; - } - `); - - const expected = unpad(` - for (var i = 0; i < 0; i++) { - var i = 0, - k = 0; - } - `); - - expect(transform(source)).toBe(expected); - }); + k = 0; + } + ` + ); }); diff --git a/packages/babel-plugin-transform-minify-booleans/__tests__/booleans-test.js b/packages/babel-plugin-transform-minify-booleans/__tests__/booleans-test.js index 2034d9be2..cfcef4212 100644 --- a/packages/babel-plugin-transform-minify-booleans/__tests__/booleans-test.js +++ b/packages/babel-plugin-transform-minify-booleans/__tests__/booleans-test.js @@ -1,18 +1,17 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("boolean-plugin", () => { - it("should shorten bool", () => { - const source = "true; false;"; - const expected = "!0;!1;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should shorten bool", + ` + true; false; + `, + ` + !0;!1; + ` + ); }); diff --git a/packages/babel-plugin-transform-node-env-inline/__tests__/node-env-inline-test.js b/packages/babel-plugin-transform-node-env-inline/__tests__/node-env-inline-test.js index 7ad101310..830cecf3e 100644 --- a/packages/babel-plugin-transform-node-env-inline/__tests__/node-env-inline-test.js +++ b/packages/babel-plugin-transform-node-env-inline/__tests__/node-env-inline-test.js @@ -1,23 +1,27 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("node-env-inline-plugin", () => { - it("should inline", () => { - const prev = process.env.NODE_ENV; + let prev; + beforeAll(() => { + prev = process.env.NODE_ENV; process.env.NODE_ENV = "development"; + }); - const source = 'process.env.NODE_ENV === "development";'; - const expected = "true;"; - expect(transform(source)).toBe(expected); + thePlugin( + "should inline", + ` + process.env.NODE_ENV === "development"; + `, + ` + true; + ` + ); + afterAll(() => { process.env.NODE_ENV = prev; }); }); diff --git a/packages/babel-plugin-transform-property-literals/__tests__/transform-property-literals-test.js b/packages/babel-plugin-transform-property-literals/__tests__/transform-property-literals-test.js index 4bb30ed23..51f242309 100644 --- a/packages/babel-plugin-transform-property-literals/__tests__/transform-property-literals-test.js +++ b/packages/babel-plugin-transform-property-literals/__tests__/transform-property-literals-test.js @@ -1,113 +1,115 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); -const unpad = require("../../../utils/unpad"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("transform-property-literals-plugin", () => { - it("should strip unnecessary property literal qoutes", () => { - const source = "var x = { 'foo': 'bar' };"; - const expected = "var x = { foo: 'bar' };"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should strip unnecessary property literal qoutes", + ` + var x = { 'foo': 'bar' }; + `, + ` + var x = { foo: 'bar' }; + ` + ); - it("should strip unnecessary property literal qoutes for numbers", () => { - const source = "var x = { '1': 'bar' };"; - const expected = "var x = { 1: 'bar' };"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should strip unnecessary property literal qoutes for numbers", + ` + var x = { '1': 'bar' }; + `, + ` + var x = { 1: 'bar' }; + ` + ); - it("should not strip necessaary quotes for numeric like things", () => { - const source = unpad(` - var data = { - "00": 1, - "01": 2 - }; - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not strip necessaary quotes for numeric like things", + ` + var data = { + "00": 1, + "01": 2 + }; + ` + ); - it("should not transform invalid identifiers", () => { - const source = unpad(` - ({ - "default": null, - "import": null - }); - `); - const expected = unpad(` - ({ - default: null, - import: null - }); - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should not transform invalid identifiers", + ` + ({ + "default": null, + "import": null + }); + `, + ` + ({ + default: null, + import: null + }); + ` + ); - it("should not transform non-string properties", () => { - const source = unpad(` - ({ - foo: null - }); - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not transform non-string properties", + ` + ({ + foo: null + }); + ` + ); - it("should not transform propety keys that are computed", () => { - const source = unpad(` - ({ - [a]: null - }); - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not transform propety keys that are computed", + ` + ({ + [a]: null + }); + ` + ); - it("should not transform invalid es5 property names", () => { - const source = unpad(` - ({ - "\u2118": "wp", - "𐊧": "foo" - }); - `); - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not transform invalid es5 property names", + ` + ({ + "\u2118": "wp", + "𐊧": "foo" + }); + ` + ); - it("should transform valid ES5 unicodes as property names", () => { - const source = unpad(` - ({ - "ಠ_ಠ": "bar", - "12e34": "wut", - "\u01FC": "AE" - }) - `); - const expected = unpad(` - ({ - ಠ_ಠ: "bar", - "12e34": "wut", - \u01FC: "AE" - }); - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should transform valid ES5 unicodes as property names", + ` + ({ + "ಠ_ಠ": "bar", + "12e34": "wut", + "\u01FC": "AE" + }) + `, + ` + ({ + ಠ_ಠ: "bar", + "12e34": "wut", + \u01FC: "AE" + }); + ` + ); - it("should transform computed properties which are strings", () => { - const source = unpad(` - ({ - [ಠ_ಠ]: "foo", - ["ಠ_ಠ"]: "bar" - }); - `); - const expected = unpad(` - ({ - [ಠ_ಠ]: "foo", - ಠ_ಠ: "bar" - }); - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should transform computed properties which are strings", + ` + ({ + [ಠ_ಠ]: "foo", + ["ಠ_ಠ"]: "bar" + }); + `, + ` + ({ + [ಠ_ಠ]: "foo", + ಠ_ಠ: "bar" + }); + ` + ); }); diff --git a/packages/babel-plugin-transform-regexp-constructors/__tests__/transform-regexp-constructors-test.js b/packages/babel-plugin-transform-regexp-constructors/__tests__/transform-regexp-constructors-test.js index bd8f71875..d9acc05e4 100644 --- a/packages/babel-plugin-transform-regexp-constructors/__tests__/transform-regexp-constructors-test.js +++ b/packages/babel-plugin-transform-regexp-constructors/__tests__/transform-regexp-constructors-test.js @@ -1,98 +1,140 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("transform-regexp-constructors-plugin", () => { - it("should not duplicate forward-slash escapes", () => { - const source = String.raw`var x = new RegExp('\\/');`; - const expected = String.raw`var x = /\//;`; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should not duplicate forward-slash escapes", + String.raw` + var x = new RegExp('\\/'); + `, + String.raw` + var x = /\//; + ` + ); - it("should transform newlines fine", () => { - const source = String.raw`var x = new RegExp('\\n');`; - const expected = String.raw`var x = /\n/;`; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should transform newlines fine", + String.raw` + var x = new RegExp('\\n'); + `, + String.raw` + var x = /\n/; + ` + ); - it("should transform unicode newlines fine", () => { - const source = String.raw`var x = new RegExp('\u2028\u2029');`; - const expected = String.raw`var x = /\u2028\u2029/;`; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should transform unicode newlines fine", + String.raw` + var x = new RegExp('\u2028\u2029'); + `, + String.raw` + var x = /\u2028\u2029/; + ` + ); - it("should transform RegExp constructors with string literals", () => { - const source = "var x = new RegExp('ab+c');"; - const expected = "var x = /ab+c/;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should transform RegExp constructors with string literals", + ` + var x = new RegExp('ab+c'); + `, + ` + var x = /ab+c/; + ` + ); - it("should transform RegExp calls with string literals", () => { - const source = "var x = RegExp('ab+c');"; - const expected = "var x = /ab+c/;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should transform RegExp calls with string literals", + ` + var x = RegExp('ab+c'); + `, + ` + var x = /ab+c/; + ` + ); - it("should transform RegExp constructors with flags", () => { - const source = "var x = new RegExp('ab+c', 'gimuy');"; - const expected = "var x = /ab+c/gimuy;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should transform RegExp constructors with flags", + ` + var x = new RegExp('ab+c', 'gimuy'); + `, + ` + var x = /ab+c/gimuy; + ` + ); - it("should transform RegExp escapes", () => { - const source = String.raw`var x = new RegExp('\\w+\\s');`; - const expected = String.raw`var x = /\w+\s/;`; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should transform RegExp escapes", + String.raw` + var x = new RegExp('\\w+\\s'); + `, + String.raw` + var x = /\w+\s/; + ` + ); - it("should not transform RegExp constructors with expressions", () => { - const source = "var x = new RegExp(foo(), 'g');"; - const expected = source; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should not transform RegExp constructors with expressions", + ` + var x = new RegExp(foo(), 'g'); + ` + ); - it("should transform empty RegExp constructor", () => { - const source = "var x = new RegExp();"; - const expected = "var x = /(?:)/;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should transform empty RegExp constructor", + ` + var x = new RegExp(); + `, + ` + var x = /(?:)/; + ` + ); - it("should transform RegExp constructor with empty string", () => { - const source = "var x = new RegExp('');"; - const expected = "var x = /(?:)/;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should transform RegExp constructor with empty string", + ` + var x = new RegExp(''); + `, + ` + var x = /(?:)/; + ` + ); - it("should resolve expressions and const references", () => { - const source = ` -const foo = "ab+"; -const bar = "c\\\\w"; -const flags = "g"; -const ret = new RegExp(foo + bar + "d", flags);`; - const expected = ` -const foo = "ab+"; -const bar = "c\\\\w"; -const flags = "g"; -const ret = /ab+c\\wd/g;`; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should resolve expressions and const references", + ` + const foo = "ab+"; + const bar = "c\\\\w"; + const flags = "g"; + const ret = new RegExp(foo + bar + "d", flags); + `, + ` + const foo = "ab+"; + const bar = "c\\\\w"; + const flags = "g"; + const ret = /ab+c\\wd/g; + ` + ); - it("should prettify special whitespaces", () => { - const source = String.raw`var x = new RegExp('\b\f\v\t\r\n\n');`; - const expected = String.raw`var x = /[\b]\f\v \r\n\n/;`; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should prettify special whitespaces", + String.raw` + var x = new RegExp('\b\f\v\t\r\n\n'); + `, + String.raw` + var x = /[\b]\f\v \r\n\n/; + ` + ); - it("should escape forward slashes", () => { - const source = String.raw`var x = new RegExp('/x/');`; - const expected = String.raw`var x = /\/x\//;`; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should escape forward slashes", + String.raw` + var x = new RegExp('/x/'); + `, + String.raw` + var x = /\/x\//; + ` + ); }); diff --git a/packages/babel-plugin-transform-remove-console/__tests__/remove-console-test.js b/packages/babel-plugin-transform-remove-console/__tests__/remove-console-test.js index a61a6787c..054c43111 100644 --- a/packages/babel-plugin-transform-remove-console/__tests__/remove-console-test.js +++ b/packages/babel-plugin-transform-remove-console/__tests__/remove-console-test.js @@ -1,157 +1,146 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); -const unpad = require("../../../utils/unpad"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("remove-console-plugin", () => { - it("statement-nested", () => { - const source = unpad(` - function foo() { - console.log("foo"); - blah(); - } - `); - - const expected = unpad(` - function foo() { - blah(); - } - `); - expect(transform(source)).toBe(expected); - }); - - it("expression-nested", () => { - const source = unpad(` - function foo() { - true && console.log("foo"); - blah(); - } - `); - - const expected = unpad(` - function foo() { - true && void 0; - blah(); - } - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "statement-nested", + ` + function foo() { + console.log("foo"); + blah(); + } + `, + ` + function foo() { + blah(); + } + ` + ); - it("expression-top-level", () => { - const source = unpad(` + thePlugin( + "expression-nested", + ` + function foo() { true && console.log("foo"); blah(); - `); - - const expected = unpad(` + } + `, + ` + function foo() { true && void 0; blah(); - `); - expect(transform(source)).toBe(expected); - }); - - it("statement-top-level", () => { - const source = unpad(` - console.log("foo"); - blah(); - `); + } + ` + ); - const expected = unpad(` - blah(); - `); - expect(transform(source).trim()).toBe(expected); - }); + thePlugin( + "expression-top-level", + ` + true && console.log("foo"); + blah(); + `, + ` + true && void 0; + blah(); + ` + ); - it("statement no block", () => { - const source = unpad(` - if (blah) console.log(blah); - for (;;) console.log(blah); - for (var blah in []) console.log(blah); - for (var blah of []) console.log(blah); - while (blah) console.log(blah); - do console.log(blah); while (blah); - `); + thePlugin( + "statement-top-level", + ` + console.log("foo"); + blah(); + `, + ` + blah(); + ` + ); - const expected = unpad(` - if (blah) {} - for (;;) {} - for (var blah in []) {} - for (var blah of []) {} - while (blah) {} - do {} while (blah); - `); - expect(transform(source).trim()).toBe(expected); - }); + thePlugin( + "statement no block", + ` + if (blah) console.log(blah); + for (;;) console.log(blah); + for (var blah in []) console.log(blah); + for (var blah of []) console.log(blah); + while (blah) console.log(blah); + do console.log(blah); while (blah); + `, + ` + if (blah) {} + for (;;) {} + for (var blah in []) {} + for (var blah of []) {} + while (blah) {} + do {} while (blah); + ` + ); - it("should remove console.* assignments to other variables", () => { - const source = unpad(` - const a = console.log; - a(); - const b = console.log.bind(console); - b("asdf"); - var x = console.log ? console.log('log') : foo(); - function foo() { - if (console.error) { - console.error("Errored"); - } + thePlugin( + "should remove console.* assignments to other variables", + ` + const a = console.log; + a(); + const b = console.log.bind(console); + b("asdf"); + var x = console.log ? console.log('log') : foo(); + function foo() { + if (console.error) { + console.error("Errored"); } - console.log.call(console, "foo"); - console.log.apply(null, {}); - `); - const expected = unpad(` - const a = function () {}; - a(); - const b = function () {}; - b("asdf"); - var x = function () {} ? void 0 : foo(); - function foo() { - if (function () {}) {} - } - `); - expect(transform(source)).toBe(expected); - }); + } + console.log.call(console, "foo"); + console.log.apply(null, {}); + `, + ` + const a = function () {}; + a(); + const b = function () {}; + b("asdf"); + var x = function () {} ? void 0 : foo(); + function foo() { + if (function () {}) {} + } + ` + ); - it("should NOT remove local bindings of name console", () => { - const source = unpad(` - function foo(console) { - console.foo("hi"); - const bar = console.foo.bind(console); - } - function bar(a) { - const { console } = a; - a.b = console => console.bar("bar"); - if (console.foo.call(console, "bar")) { - return; - } + thePlugin( + "should NOT remove local bindings of name console", + ` + function foo(console) { + console.foo("hi"); + const bar = console.foo.bind(console); + } + function bar(a) { + const { console } = a; + a.b = console => console.bar("bar"); + if (console.foo.call(console, "bar")) { + return; } - `); - expect(transform(source)).toBe(source); - }); + } + ` + ); - it("should convert assigments to no-op", () => { - const source = unpad(` - function foo() { - console.foo = function foo() { - console.log("foo"); - }; - console.error = myConsoleError; - console.foo(); - console.error("asdf"); - } - `); - const expected = unpad(` - function foo() { - console.foo = function () {}; - console.error = function () {}; - } - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should convert assigments to no-op", + ` + function foo() { + console.foo = function foo() { + console.log("foo"); + }; + console.error = myConsoleError; + console.foo(); + console.error("asdf"); + } + `, + ` + function foo() { + console.foo = function () {}; + console.error = function () {}; + } + ` + ); }); diff --git a/packages/babel-plugin-transform-remove-debugger/__tests__/remove-debugger-test.js b/packages/babel-plugin-transform-remove-debugger/__tests__/remove-debugger-test.js index e40bf8d1f..5370e1e84 100644 --- a/packages/babel-plugin-transform-remove-debugger/__tests__/remove-debugger-test.js +++ b/packages/babel-plugin-transform-remove-debugger/__tests__/remove-debugger-test.js @@ -1,46 +1,46 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); -const unpad = require("../../../utils/unpad"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("remove-debugger-plugin", () => { - it("should remove debugger", () => { - const source = "debugger;"; - const expected = ""; - expect(transform(source)).toBe(expected); - }); - - it("should remove debugger only", () => { - const source = "debugger; 1;"; - const expected = "1;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should remove debugger", + ` + debugger; + `, + ` + ` + ); - it("statement no block", () => { - const source = unpad(` - if (blah) debugger; - for (;;) debugger; - for (var blah in []) debugger; - for (var blah of []) debugger; - while (blah) debugger; - do debugger; while (blah); - `); + thePlugin( + "should remove debugger only", + ` + debugger; 1; + `, + ` + 1; + ` + ); - const expected = unpad(` - if (blah) {} - for (;;) {} - for (var blah in []) {} - for (var blah of []) {} - while (blah) {} - do {} while (blah); - `); - expect(transform(source).trim()).toBe(expected); - }); + thePlugin( + "statement no block", + ` + if (blah) debugger; + for (;;) debugger; + for (var blah in []) debugger; + for (var blah of []) debugger; + while (blah) debugger; + do debugger; while (blah); + `, + ` + if (blah) {} + for (;;) {} + for (var blah in []) {} + for (var blah of []) {} + while (blah) {} + do {} while (blah); + ` + ); }); diff --git a/packages/babel-plugin-transform-remove-undefined/__tests__/babel-plugin-transform-remove-undefined-test.js b/packages/babel-plugin-transform-remove-undefined/__tests__/babel-plugin-transform-remove-undefined-test.js index 74cb3abf4..671c46a9c 100644 --- a/packages/babel-plugin-transform-remove-undefined/__tests__/babel-plugin-transform-remove-undefined-test.js +++ b/packages/babel-plugin-transform-remove-undefined/__tests__/babel-plugin-transform-remove-undefined-test.js @@ -1,215 +1,243 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); -const unpad = require("../../../utils/unpad"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("transform-remove-undefined-plugin", () => { - it("should remove multiple undefined assignments in 1 statement", () => { - const source = "let a = undefined, b = 3, c = undefined, d;"; - const expected = "let a,\n b = 3,\n c,\n d;"; - expect(transform(source)).toBe(expected); - }); - - it("should remove let-assignments to undefined", () => { - const source = "let a = undefined;"; - const expected = "let a;"; - expect(transform(source)).toBe(expected); - }); - - it("should remove let-assignments to void 0", () => { - const source = "let a = void 0;"; - const expected = "let a;"; - expect(transform(source)).toBe(expected); - }); - - it("should not remove const-assignments to undefined", () => { - const source = "const a = undefined;"; - expect(transform(source)).toBe(source); - }); - - it("should remove undefined return value", () => { - const source = unpad(` - function foo() { - return undefined; - }`); - const expected = unpad(` - function foo() { - return; - }`); - expect(transform(source)).toBe(expected); - }); - - it("should remove var declarations in functions", () => { - const source = unpad(` - function foo() { - var a = undefined; - }`); - const expected = unpad(` - function foo() { - var a; - }`); - expect(transform(source)).toBe(expected); - }); - - it("should remove let-assignments in inner blocks", () => { - const source = unpad(` - let a = 1; - { - let a = undefined; - }`); - const expected = unpad(` - let a = 1; - { - let a; - }`); - expect(transform(source)).toBe(expected); - }); - - it("should remove var-assignments in loops if no modify", () => { - const source = unpad(` - for (var a = undefined;;) { - var b = undefined; - }`); - const expected = unpad(` - for (var a;;) { - var b; - }`); - expect(transform(source)).toBe(expected); - }); - - it("should not remove var-assignments in loops if modify", () => { - const source = unpad(` - for (var a;;) { - var b = undefined; - console.log(b); - b = 3; - }`); - expect(transform(source)).toBe(source); - }); - - it("should not remove var-assignments if referenced before", () => { - const source = unpad(` - function foo() { - a = 3; - var a = undefined; - }`); - expect(transform(source)).toBe(source); - }); - - it("should not remove nested var-assignments if referenced before", () => { - const source = unpad(` - function foo() { - aa = 3; - var { a: aa, b: bb } = undefined; - }`); - expect(transform(source)).toBe(source); - }); - - it("should not remove if lval is reference before via a function", () => { - const source = unpad(` - function foo() { - bar(); - var x = undefined; - console.log(x); - function bar() { - x = 3; - } - }`); - expect(transform(source)).toBe(source); - }); - - it("should remove if not referenced in any way before", () => { - const source = unpad(` - function foo() { - var x = undefined; - bar(); - console.log(x); - function bar() { - x = 3; - } - }`); - const expected = unpad(` - function foo() { - var x; - bar(); - console.log(x); - function bar() { - x = 3; - } - }`); - expect(transform(source)).toBe(expected); - }); - - it("should not remove on mutually recursive function", () => { - const source = unpad(` - function foo() { - a(); - var c = undefined; - function a() { - b(); - } - function b() { - a(); - c = 3; - } - }`); - expect(transform(source)).toBe(source); - }); - - it("should not remove if rval has side effects", () => { - const source = unpad(` - function foo() { - var a = void b(); - return void bar(); - }`); - expect(transform(source)).toBe(source); - }); - - it("should remove from sequence expressions", () => { - const source = unpad(` - a = b, void 0, b = c, d.e.f(), void 0, hello.world(); - `); - const expected = unpad(` - a = b, b = c, d.e.f(), hello.world(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should NOT remove last undefined from sequence expressions", () => { - const source = unpad(` - if (foo.bar(), void 0) { - foo.baz(); + thePlugin( + "should remove multiple undefined assignments in 1 statement", + ` + let a = undefined, b = 3, c = undefined, d; + `, + ` + let a, + b = 3, + c, + d; + ` + ); + + thePlugin( + "should remove let-assignments to undefined", + ` + let a = undefined; + `, + ` + let a; + ` + ); + + thePlugin( + "should remove let-assignments to void 0", + ` + let a = void 0; + `, + ` + let a; + ` + ); + + thePlugin( + "should not remove const-assignments to undefined", + ` + const a = undefined; + ` + ); + + thePlugin( + "should remove undefined return value", + ` + function foo() { + return undefined; + } + `, + ` + function foo() { + return; + } + ` + ); + + thePlugin( + "should remove var declarations in functions", + ` + function foo() { + var a = undefined; + } + `, + ` + function foo() { + var a; + } + ` + ); + + thePlugin( + "should remove let-assignments in inner blocks", + ` + let a = 1; + { + let a = undefined; + } + `, + ` + let a = 1; + { + let a; + } + ` + ); + + thePlugin( + "should remove var-assignments in loops if no modify", + ` + for (var a = undefined;;) { + var b = undefined; + } + `, + ` + for (var a;;) { + var b; + } + ` + ); + + thePlugin( + "should not remove var-assignments in loops if modify", + ` + for (var a;;) { + var b = undefined; + console.log(b); + b = 3; + } + ` + ); + + thePlugin( + "should not remove var-assignments if referenced before", + ` + function foo() { + a = 3; + var a = undefined; + } + ` + ); + + thePlugin( + "should not remove nested var-assignments if referenced before", + ` + function foo() { + aa = 3; + var { a: aa, b: bb } = undefined; + } + ` + ); + + thePlugin( + "should not remove if lval is reference before via a function", + ` + function foo() { + bar(); + var x = undefined; + console.log(x); + function bar() { + x = 3; + } + } + ` + ); + + thePlugin( + "should remove if not referenced in any way before", + ` + function foo() { + var x = undefined; + bar(); + console.log(x); + function bar() { + x = 3; } + } + `, + ` + function foo() { + var x; + bar(); + console.log(x); function bar() { - return a.b(), void 0; + x = 3; + } + } + ` + ); + + thePlugin( + "should not remove on mutually recursive function", + ` + function foo() { + a(); + var c = undefined; + function a() { + b(); + } + function b() { + a(); + c = 3; } - `); - expect(transform(source)).toBe(source); - }); - - it("should remove last undefined from sequence expressions if safe", () => { - const source = unpad(` - a = b, void 0, b = c, d.e.f(), void 0, hello.world(), void 0; - `); - const expected = unpad(` - a = b, b = c, d.e.f(), hello.world(); - `); - expect(transform(source)).toBe(expected); - }); - - it("should remove not remove local undefined", () => { - const source = unpad(` - function foo(undefined) { - a = b, undefined; - return undefined; - }`); - expect(transform(source)).toBe(source); - }); + } + ` + ); + + thePlugin( + "should not remove if rval has side effects", + ` + function foo() { + var a = void b(); + return void bar(); + } + ` + ); + + thePlugin( + "should remove from sequence expressions", + ` + a = b, void 0, b = c, d.e.f(), void 0, hello.world(); + `, + ` + a = b, b = c, d.e.f(), hello.world(); + ` + ); + + thePlugin( + "should NOT remove last undefined from sequence expressions", + ` + if (foo.bar(), void 0) { + foo.baz(); + } + function bar() { + return a.b(), void 0; + } + ` + ); + + thePlugin( + "should remove last undefined from sequence expressions if safe", + ` + a = b, void 0, b = c, d.e.f(), void 0, hello.world(), void 0; + `, + ` + a = b, b = c, d.e.f(), hello.world(); + ` + ); + + thePlugin( + "should not remove local undefined", + ` + function foo(undefined) { + a = b, undefined; + return undefined; + } + ` + ); }); diff --git a/packages/babel-plugin-transform-simplify-comparison-operators/__tests__/strict-equals-test.js b/packages/babel-plugin-transform-simplify-comparison-operators/__tests__/strict-equals-test.js index 9467c9138..0d7b734e3 100644 --- a/packages/babel-plugin-transform-simplify-comparison-operators/__tests__/strict-equals-test.js +++ b/packages/babel-plugin-transform-simplify-comparison-operators/__tests__/strict-equals-test.js @@ -1,76 +1,70 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); -const unpad = require("../../../utils/unpad"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("simplify-comparison-operators-plugin", () => { - it("should simplify comparison", () => { - const source = "'function' === typeof a;"; - const expected = "'function' == typeof a;"; - expect(transform(source)).toBe(expected); - }); - - it("should simplify comparison operations", () => { - const source = "null === null;"; - const expected = "null == null;"; - expect(transform(source)).toBe(expected); - }); - - it("should comparison operations 2", () => { - const source = unpad(` - var x = null; - x === null; - `); - const expected = unpad(` - var x = null; - x == null; - `); - - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should simplify comparison", + ` + 'function' === typeof a; + `, + ` + 'function' == typeof a; + ` + ); - it("should not simplify comparison", () => { - const source = unpad(` - var x; - x === null; - `); - const expected = unpad(` - var x; - x === null; - `); + thePlugin( + "should simplify comparison operations", + ` + null === null; + `, + ` + null == null; + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should comparison operations 2", + ` + var x = null; + x === null; + `, + ` + var x = null; + x == null; + ` + ); - it("should not simplify comparison 2", () => { - const source = unpad(` - var x; - if (wow) x = foo(); - x === null; - `); - const expected = unpad(` - var x; - if (wow) x = foo(); - x === null; - `); + thePlugin( + "should not simplify comparison", + ` + var x; + x === null; + ` + ); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should not simplify comparison 2", + ` + var x; + if (wow) x = foo(); + x === null; + ` + ); - it("should not simplify comparison if already simplified", function() { - const source = 'typeof 1 == "number";'; - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not simplify comparison if already simplified", + ` + typeof 1 == "number"; + ` + ); - it("should not simplify comparison if not equality check", function() { - const source = "a > b;"; - expect(transform(source)).toBe(source); - }); + thePlugin( + "should not simplify comparison if not equality check", + ` + a > b; + ` + ); }); diff --git a/packages/babel-plugin-transform-undefined-to-void/__tests__/undefined-test.js b/packages/babel-plugin-transform-undefined-to-void/__tests__/undefined-test.js index b25bbb31a..db1e960ec 100644 --- a/packages/babel-plugin-transform-undefined-to-void/__tests__/undefined-test.js +++ b/packages/babel-plugin-transform-undefined-to-void/__tests__/undefined-test.js @@ -1,24 +1,27 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const plugin = require("../src/index"); - -function transform(code) { - return babel.transform(code, { - plugins: [plugin] - }).code; -} +const thePlugin = require("../../../utils/test-transform")( + require("../src/index") +); describe("undefined-plugin", () => { - it("should turn undefined into void 0", () => { - const source = "var foo;foo === undefined;"; - const expected = "var foo;foo === void 0;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn undefined into void 0", + ` + var foo;foo === undefined; + `, + ` + var foo;foo === void 0; + ` + ); - it("should turn undefined into void 0 in a MemberExpression", () => { - const source = "var foo;foo === undefined.foo;"; - const expected = "var foo;foo === (void 0).foo;"; - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should turn undefined into void 0 in a MemberExpression", + ` + var foo;foo === undefined.foo; + `, + ` + var foo;foo === (void 0).foo; + ` + ); }); diff --git a/packages/babel-preset-babili/__tests__/preset-tests.js b/packages/babel-preset-babili/__tests__/preset-tests.js index e7fefe395..e4226bb38 100644 --- a/packages/babel-preset-babili/__tests__/preset-tests.js +++ b/packages/babel-preset-babili/__tests__/preset-tests.js @@ -1,150 +1,145 @@ jest.autoMockOff(); -const babel = require("babel-core"); -const unpad = require("../../../utils/unpad"); - -function transform(code, options = {}, sourceType = "script") { - return babel.transform(code, { - sourceType, - minified: false, - presets: [[require("../src/index"), options]] - }).code; -} +const thePlugin = require("../../../utils/test-transform")(null, { + plugins: [], + minified: false, + presets: [require("../src/index")] +}); describe("preset", () => { // https://github.com/babel/babili/issues/122 - it("should fix issue#122", () => { - const source = unpad(` - function foo() { - var a, b, c; - if (a) { - if (b) { - if (c) {} - } + thePlugin( + "should fix issue#122", + ` + function foo() { + var a, b, c; + if (a) { + if (b) { + if (c) {} + } + } else { + if (b) { } else { - if (b) { - } else { - if (c) {} - } + if (c) {} } } - `); - const expected = unpad(` - function foo() { - var d, a, b; - d ? a && b : a || b; - } - `); - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function foo() { + var d, a, b; + d ? a && b : a || b; + } + ` + ); - it("should fix remove comments", () => { - const source = unpad(` - var asdf = 1; // test - `); - const expected = unpad(` - var asdf = 1; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should fix remove comments", + ` + var asdf = 1; // test + `, + ` + var asdf = 1; + ` + ); - it("should keep license/preserve annotated comments", () => { - const source = unpad(` - /* @license */ - var asdf = 1; - `); - const expected = unpad(` - /* @license */ - var asdf = 1; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should keep license/preserve annotated comments", + ` + /* @license */ + var asdf = 1; + `, + ` + /* @license */ + var asdf = 1; + ` + ); - it("should fix issue#385 - impure if statements with Sequence and DCE", () => { - const source = unpad(` - a = b; - c = d; - if (false) { - const x = y - } - `); - const expected = unpad(` - a = b, c = d; - `); - expect(transform(source)).toBe(expected); - }); + thePlugin( + "should fix issue#385 - impure if statements with Sequence and DCE", + ` + a = b; + c = d; + if (false) { + const x = y + } + `, + ` + a = b, c = d; + ` + ); - it("should fix issue#402 - lifting var decl & DCE", () => { - const source = unpad(` - function a() { - if (0) { - for (var i;;) { - var something = 5; - } + thePlugin( + "should fix issue#402 - lifting var decl & DCE", + ` + function a() { + if (0) { + for (var i;;) { + var something = 5; } } - a(); - `); - const expected = unpad(` - function a() {} - a(); - `); - expect(transform(source)).toBe(expected); - }); + } + a(); + `, + ` + function a() {} + a(); + ` + ); - it("should fix issue#425 - mangles the alaises from builtins transform", () => { - const source = unpad(` - function a (){ - const d = Math.max(foo, bar); - function b() { - Math.max(foo, bar) * Math.floor(baz); - } - function c() { - Math.max(foo, bar) * Math.floor(baz); - } + thePlugin( + "should fix issue#425 - mangles the alaises from builtins transform", + ` + function a (){ + const d = Math.max(foo, bar); + function b() { + Math.max(foo, bar) * Math.floor(baz); } - `); - const expected = unpad(` - function a() { - var a = Math.floor, - b = Math.max; - b(foo, bar); + function c() { + Math.max(foo, bar) * Math.floor(baz); } - `); - expect(transform(source)).toBe(expected); - }); + } + `, + ` + function a() { + var a = Math.floor, + b = Math.max; + b(foo, bar); + } + ` + ); - it("should fix bug#326 - object destructuring", () => { - const source = unpad(` - function a() { - let foo, bar, baz; - ({foo, bar, baz} = {}); - return {foo, bar, baz}; - } - `); - const expected = unpad(` - function a() { - let a, b, c; + thePlugin( + "should fix bug#326 - object destructuring", + ` + function a() { + let foo, bar, baz; + ({foo, bar, baz} = {}); + return {foo, bar, baz}; + } + `, + ` + function a() { + let a, b, c; - return ({ foo: a, bar: b, baz: c } = {}), { foo: a, bar: b, baz: c }; - } - `); - expect(transform(source)).toBe(expected); - }); + return ({ foo: a, bar: b, baz: c } = {}), { foo: a, bar: b, baz: c }; + } + ` + ); - it("should fix bug#568 - conflicts b/w builtIns and mangle", () => { - const source = unpad(` - (function () { - return [Math.pi, Math.pi]; - })(); - `); - const expected = unpad(` - (function () { - var a = Math.pi; + thePlugin( + "should fix bug#568 - conflicts b/w builtIns and mangle", + ` + (function () { + return [Math.pi, Math.pi]; + })(); + `, + ` + (function () { + var a = Math.pi; - return [a, a]; - })(); - `); - expect(transform(source)).toBe(expected); - }); + return [a, a]; + })(); + ` + ); }); diff --git a/utils/test-transform.js b/utils/test-transform.js new file mode 100644 index 000000000..645757a7c --- /dev/null +++ b/utils/test-transform.js @@ -0,0 +1,78 @@ +const babel = require("babel-core"); + +const unpad = require("./unpad"); + +function _transform(source, options) { + return babel.transform(unpad(source), options).code.trim(); +} + +function makeTester( + plugins, + opts, + { transform = _transform, check }, + excludeKeys = [] +) { + if (!Array.isArray(plugins)) { + plugins = [plugins]; + } + const thePlugin = (name, source, expected = source, babelOpts) => { + if (typeof expected === "object") { + babelOpts = expected; + expected = source; + } + const { stack } = new Error(); + const options = Object.assign( + { plugins, sourceType: "script" }, + opts, + babelOpts + ); + it(name, () => { + const transformed = transform(source, options); + try { + check({ + transformed, + expected: unpad(expected), + source: unpad(source) + }); + } catch (e) { + // use the stack from outside the it() clause + // (the one inside the clause doesn’t show the actual test code) + e.stack = stack; + throw e; + } + }); + }; + thePlugin.skip = name => it.skip(name); + if (!excludeKeys.includes("inEachLine")) { + thePlugin.inEachLine = makeTester( + plugins, + opts, + { + transform(source, options) { + return unpad(source) + .split("\n") + .map(line => _transform(line, options)) + .join("\n"); + }, + check + }, + excludeKeys.concat("inEachLine") + ); + } + return thePlugin; +} + +exports = module.exports = (plugins, opts) => + makeTester(plugins, opts, { + check({ transformed, expected }) { + expect(transformed).toBe(expected); + } + }); + +exports.snapshot = (plugins, opts) => + makeTester(plugins, opts, { + check({ transformed, source }) { + // Jest arranges in alphabetical order, So keeping it as _source + expect({ _source: source, expected: transformed }).toMatchSnapshot(); + } + }); From be7e0cedc69dbd433240abff9c90be2296e52a74 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Thu, 29 Jun 2017 12:54:26 -0400 Subject: [PATCH 2/4] Copy-edit test names --- .../__tests__/constant-folding-test.js | 6 +- .../__tests__/dead-code-elimination-test.js | 514 +++++++----------- .../__tests__/flip-comparisons-test.js | 30 +- .../__tests__/infinity-test.js | 12 +- .../__tests__/mangle-names-test.js | 70 +-- .../__tests__/numeric-literals-test.js | 2 +- .../__tests__/simplify-test.js | 64 +-- .../__tests__/type-constructors-test.js | 42 +- .../transform-inline-consecutive-adds-test.js | 40 +- ...ansform-member-expression-literals-test.js | 6 +- .../transform-merge-sibling-variables-test.js | 24 +- .../__tests__/booleans-test.js | 2 +- .../__tests__/node-env-inline-test.js | 2 +- .../transform-property-literals-test.js | 6 +- .../transform-regexp-constructors-test.js | 20 +- .../__tests__/remove-console-test.js | 16 +- .../__tests__/remove-debugger-test.js | 6 +- .../__tests__/strict-equals-test.js | 28 +- .../__tests__/undefined-test.js | 4 +- 19 files changed, 344 insertions(+), 550 deletions(-) diff --git a/packages/babel-plugin-minify-constant-folding/__tests__/constant-folding-test.js b/packages/babel-plugin-minify-constant-folding/__tests__/constant-folding-test.js index b831791e2..60340b73a 100644 --- a/packages/babel-plugin-minify-constant-folding/__tests__/constant-folding-test.js +++ b/packages/babel-plugin-minify-constant-folding/__tests__/constant-folding-test.js @@ -75,7 +75,7 @@ describe("constant-folding-plugin", () => { ); thePlugin.skip( - "should handle html comment escape", + "should handle HTML comment escape", ` " { ` ); thePlugin( - "should ignore bad calls to array expression methods", + "should ignore bad calls to array literal methods", ` [1, 2, 3][concat]([4, 5, 6]); [a, "b", "c"].join(); @@ -169,7 +169,7 @@ describe("constant-folding-plugin", () => { ` ); thePlugin( - "should ignore bad calls to string expression methods", + "should ignore bad calls to string literal methods", ` "abc".something; "abc"["something"]; diff --git a/packages/babel-plugin-minify-dead-code-elimination/__tests__/dead-code-elimination-test.js b/packages/babel-plugin-minify-dead-code-elimination/__tests__/dead-code-elimination-test.js index fa4e7dd29..5b270e870 100644 --- a/packages/babel-plugin-minify-dead-code-elimination/__tests__/dead-code-elimination-test.js +++ b/packages/babel-plugin-minify-dead-code-elimination/__tests__/dead-code-elimination-test.js @@ -106,7 +106,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should NOT remove params when keepFnArgs is true (preserve fn.length)", + "should NOT remove params when keepFnArgs is true, preserving Function#length", ` function foo(p) { return 1; @@ -132,7 +132,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should handle all cases of parameter list - and remove unused ones", + "should remove unused parameters, except ones with side effects", ` function a(foo, bar, baz) { return foo; @@ -176,7 +176,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should inline binding with one reference", + "should inline bindings with only one reference", ` function foo() { var x = 1; @@ -190,9 +190,9 @@ describe("dce-plugin", () => { ` ); - // This isn't considered pure. (it should) + // This isn’t considered pure. (it should be) thePlugin( - "should inline binding with one reference 2", + "should inline binding with one reference in an object literal", ` function foo() { var y = 1, x = { y: y }; @@ -207,14 +207,14 @@ describe("dce-plugin", () => { ); thePlugin( - "should not inline objects literals in loops", + "should not inline object literals in loops", ` function foo() { var x = { y: 1 }; while (true) foo(x); var y = { y: 1 }; for (;;) foo(y); - var z = ['foo']; + var z = ["foo"]; while (true) foo(z); var bar = function () {}; while (true) foo(bar); @@ -223,7 +223,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should not inline object literals in exprs in loops", + "should not inline object literals in expressions in loops", ` function a(p) { var w = p || []; @@ -235,26 +235,26 @@ describe("dce-plugin", () => { ); thePlugin( - "should inline objects in if statements", + "should inline object literals in if statements", ` function foo() { - var x = { y: 1 }, y = ['foo'], z = function () {}; + var x = { y: 1 }, y = ["foo"], z = function () {}; if (wat) foo(x, y, z); } `, ` function foo() { - if (wat) foo({ y: 1 }, ['foo'], function () {}); + if (wat) foo({ y: 1 }, ["foo"], function () {}); } ` ); thePlugin( - "should not inline objects in functions", + "should not inline object literals in functions", ` function foo() { var x = { y: 1 }, - y = ['foo'], + y = ["foo"], z = function () {}; f(function () { foo(x, y, z); @@ -298,7 +298,9 @@ describe("dce-plugin", () => { ` ); - thePlugin("should inline function decl", ` + thePlugin( + "should inline function declarations if they’re only called once", + ` function foo() { function x() { return 1; @@ -349,26 +351,13 @@ describe("dce-plugin", () => { thePlugin( "should handle recursion", ` - function baz() { + function test1() { var bar = function foo(config) { return foo; }; exports.foo = bar; } - `, - ` - function baz() { - exports.foo = function foo() { - return foo; - }; - } - ` - ); - - thePlugin( - "should handle recursion 2", - ` - function baz() { + function test2() { var foo = function foo(config) { return foo; }; @@ -376,7 +365,12 @@ describe("dce-plugin", () => { } `, ` - function baz() { + function test1() { + exports.foo = function foo() { + return foo; + }; + } + function test2() { exports.foo = function foo() { return foo; }; @@ -435,6 +429,10 @@ describe("dce-plugin", () => { return; } } + function bar() { + y(); + return; + } `, ` function foo() { @@ -442,26 +440,14 @@ describe("dce-plugin", () => { y(); } } - ` - ); - - thePlugin( - "should remove redundant returns part 2", - ` - function foo() { - y(); - return; - } - `, - ` - function foo() { + function bar() { y(); } ` ); thePlugin( - "should remove redundant returns (complex)", + "should remove complex redundant returns", ` function foo() { if (a) { @@ -485,7 +471,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should keep needed returns", + "should keep non-redundant returns", ` function foo() { if (a) { @@ -507,7 +493,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should remove code unreachable after return", + "should remove unreachable code after a return statement", ` function foo() { z(); @@ -523,7 +509,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should be fine with fun decl after return", + "should keep function declarations after a return statement", ` function foo() { z(); @@ -547,7 +533,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should handle returns that were orphaned", + "should handle orpahaned returns", ` var a = true; function foo() { @@ -562,7 +548,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should handle returns that were orphaned 2", + "should handle orpahaned returns with a value", ` var a = true; function foo() { @@ -579,7 +565,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should handle orphaned + redundant returns", + "should handle orphaned, redundant returns", ` var x = true; function foo() { @@ -605,7 +591,7 @@ describe("dce-plugin", () => { thePlugin( "should remove functions only called in themselves", ` - function foo() { + function test1() { function baz() { function bar() { baz(); @@ -614,16 +600,7 @@ describe("dce-plugin", () => { bar(); } } - `, - ` - function foo() {} - ` - ); - - thePlugin( - "should remove functions only called in themselves 2", - ` - function foo() { + function test2() { var baz = function () { function bar() { baz(); @@ -632,16 +609,7 @@ describe("dce-plugin", () => { bar(); }; } - `, - ` - function foo() {} - ` - ); - - thePlugin( - "should remove functions only called in themselves 3", - ` - function foo() { + function test3() { function boo() {} function baz() { function bar() { @@ -654,25 +622,27 @@ describe("dce-plugin", () => { } `, ` - function foo() {} + function test1() {} + function test2() {} + function test3() {} ` ); thePlugin( - "should remove functions only called in themselves 3", + "should leave externally called functions alone", ` (function () { function foo () { - console.log( 'this function was included!' ); + console.log( "this function was included!" ); } function bar () { - console.log( 'this function was not' ); + console.log( "this function was not" ); baz(); } function baz () { - console.log( 'neither was this' ); + console.log( "neither was this" ); } foo(); @@ -682,7 +652,7 @@ describe("dce-plugin", () => { (function () { (function () { - console.log('this function was included!'); + console.log("this function was included!"); })(); })(); ` @@ -708,118 +678,80 @@ describe("dce-plugin", () => { ); thePlugin( - "should remove empty if statements block", + "should negate the if block if it’s empty", ` if (a) { } else { foo(); } - if (a) { - foo(); - } else { - - } `, ` if (!a) { foo(); } - if (a) { - foo(); - } ` ); thePlugin( - "should evaluate conditional expressions", + "should remove empty else blocks", ` - true ? a() : b(); - `, - ` - a(); - ` - ); + if (a) { + foo(); + } else { - thePlugin( - "should evaluate conditional expressions 2", - ` - false ? a() : b(); + } `, ` - b(); - ` - ); + if (a) { + foo(); + } - thePlugin( - "should evaluate conditional expressions 3", - ` - 'foo' ? a() : b(); - `, - ` - a(); - ` - ); + `); thePlugin( - "should evaluate conditional expressions 4", + "should evaluate conditional expressions", ` + true ? a() : b(); + false ? a() : b(); + "foo" ? a() : b(); null ? a() : b(); + "foo" === "foo" ? a() : b(); + "foo" !== "bar" ? a() : b(); `, ` + a(); + b(); + a(); b(); - ` - ); - - thePlugin( - "should evaluate conditional expressions 5", - ` - 'foo' === 'foo' ? a() : b(); - `, - ` a(); - ` - ); - - thePlugin( - "should evaluate conditional expressions 6", - ` - 'foo' !== 'bar' ? a() : b(); - `, - ` a(); ` ); thePlugin( - "should not remove needed expressions", + "should not remove used expressions", ` var n = 1; if (foo) n; console.log(n); + + function bar(a) { + var a = a ? a : a; + } `, ` var n = 1; if (foo) ; console.log(n); - ` - ); - thePlugin( - "should not remove needed expressions", - ` - function foo(a) { - var a = a ? a : a; - } - `, - ` - function foo(a) { + function bar(a) { var a = a ? a : a; } ` ); thePlugin( - "should join the assignment and def", + "should join variable declaration and assignment", ` var x; x = 1; @@ -830,7 +762,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should not replace the wrong things", + "should perform correct replacements", ` function foo() { var n = 1; @@ -964,7 +896,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should handle vars in if statements", + "should handle variable declarations in if statements", ` function a() { if (x()) { @@ -972,6 +904,11 @@ describe("dce-plugin", () => { } bar(foo); } + + function b() { + if (x()) var foo = 1; + bar(foo); + } `, ` function a() { @@ -980,19 +917,8 @@ describe("dce-plugin", () => { } bar(foo); } - ` - ); - thePlugin( - "should handle vars in if statements 2", - ` - function a() { - if (x()) var foo = 1; - bar(foo); - } - `, - ` - function a() { + function b() { if (x()) var foo = 1; bar(foo); } @@ -1000,25 +926,14 @@ describe("dce-plugin", () => { ); thePlugin( - "should handle vars in for statements", + "should handle variable declarations in for statements", ` function a() { for (;;) var foo = 1; bar(foo); } - `, - ` - function a() { - for (;;) var foo = 1; - bar(foo); - } - ` - ); - thePlugin( - "should handle for statements 2", - ` - function a() { + function b() { for (;;) { var foo = 1; bar(foo); @@ -1027,6 +942,11 @@ describe("dce-plugin", () => { `, ` function a() { + for (;;) var foo = 1; + bar(foo); + } + + function b() { for (;;) { bar(1); } @@ -1035,7 +955,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should remove binding and assignment", + "should remove unused variable declarations and assignments", ` function a() { var a, b, c; @@ -1049,13 +969,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should nore remove binding and assignment if the value is used", - ` - function a() { - var x = 1; - while (a) wow = x += 1; - } - `, + "should not remove varibale declaration and assignment if the variable is used", ` function a() { var x = 1; @@ -1085,32 +999,18 @@ describe("dce-plugin", () => { function boo() { var bar = foo || []; if (!bar || baz.length === 0) { - return 'wow'; - } - } - `, - ` - function boo() { - var bar = foo || []; - if (!bar || baz.length === 0) { - return 'wow'; + return "wow"; } } ` ); thePlugin( - "eval the following to false", + "should eval the following to false", ` function bar () { - var x = foo || 'boo'; - bar = x === 'wow' ? ' ' + z : ''; - } - `, - ` - function bar() { - var x = foo || 'boo'; - bar = x === 'wow' ? ' ' + z : ''; + var x = foo || "boo"; + bar = x === "wow" ? " " + z : ""; } ` ); @@ -1133,7 +1033,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should remove names from NFE", + "should remove names from named function expressions", ` function bar() { return function wow() { @@ -1151,14 +1051,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should not remove names from NFE when referenced", - ` - function bar() { - return function wow() { - return wow(); - }; - } - `, + "should not remove names from named function expressions when the names are used", ` function bar() { return function wow() { @@ -1169,7 +1062,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should remove name from NFE when shadowed", + "should remove names from named function expressions when the names are shadowed", ` function bar() { return function wow() { @@ -1192,7 +1085,7 @@ describe("dce-plugin", () => { // issue#81 thePlugin( - "should NOT remove name from NFE when referenced - issue#81", + "should not regress on #81", ` (function (require, module, exports) { var Hub = function Hub(file, options) { @@ -1200,6 +1093,12 @@ describe("dce-plugin", () => { }; module.exports = Hub; })(require, module, exports); + + + (function () { + var x = function foo() {}; + module.exports = x; + })(); `, ` (function (require, module) { @@ -1207,18 +1106,7 @@ describe("dce-plugin", () => { (0, _classCallCheck3.default)(this, Hub); }; })(require, module, exports); - ` - ); - thePlugin( - "should remove name from NFE when replaced - issue#81", - ` - (function () { - var x = function foo() {}; - module.exports = x; - })(); - `, - ` (function () { module.exports = function () {}; })(); @@ -1226,7 +1114,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should preserve fn names when keepFnName is true", + "should preserve function names when keepFnName is true", ` (function () { function A() {} @@ -1275,7 +1163,7 @@ describe("dce-plugin", () => { // NCE = Named Class Expressions thePlugin( - "should remove name from NCE", + "should remove names from named class expressions", ` var Foo = class Bar {}; `, @@ -1285,7 +1173,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should not remove referenced name from NCE", + "should not remove names from named class expressions when the name is used", ` var Foo = class Bar { constructor() { @@ -1297,7 +1185,7 @@ describe("dce-plugin", () => { // issue#78 thePlugin( - "should not replace NCE with void 0 - issue#78", + "should not replace named class expressions with void 0 - issue#78", ` (function() { var B = class A { @@ -1325,7 +1213,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should handle var decl with same name as class expr name", + "should handle variable declarations with same name as the class expression name", ` (function () { var A = class A { @@ -1397,7 +1285,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should put the var in the for in", + "should put the variable declaration in the header of the for...in loop", ` function x(a) { var x; @@ -1414,7 +1302,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should put the var in the for in only when the var is alone", + "should put the variable declaration in the header of the for...in loop only when the var is alone", ` function x(a) { var x, y; @@ -1432,7 +1320,7 @@ describe("dce-plugin", () => { ); thePlugin( - "inlining should check name collision", + "inlining should avoid name collision", ` function foo() { var a = 1; @@ -1460,7 +1348,7 @@ describe("dce-plugin", () => { ); thePlugin( - "inlining should check name collision for expressions", + "inlining should avoid name collision in expressions", ` function foo() { var a = c + d; @@ -1484,50 +1372,38 @@ describe("dce-plugin", () => { ); thePlugin( - "should replace with empty statement if in body position 1", + "should replace with empty statement if the statement is the only one in a block", ` function foo() { var a = 0; while (wat()) a += 1; } - `, - ` - function foo() { - while (wat()); - } - ` - ); - thePlugin( - "should replace with empty statement if in body position 2", - ` - function foo() { + function bar() { while (wat()) 1; } + + function baz() { + while (wat()) var x; + } `, ` function foo() { while (wat()); } - ` - ); - thePlugin( - "should replace with empty statement if in body position 3", - ` - function foo() { - while (wat()) var x; + function bar() { + while (wat()); } - `, - ` - function foo() { + + function baz() { while (wat()); } ` ); thePlugin( - "it should update binding path", + "should update binding paths", ` function foo() { var key; @@ -1544,7 +1420,7 @@ describe("dce-plugin", () => { ); thePlugin.skip( - "it should evaluate and remove falsy code", + "should evaluate and remove falsy code", ` foo(0 && bar()); `, @@ -1588,7 +1464,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should preserve vars from the removed block", + "should preserve vars from removed blocks", ` if (0) {var a = foo()} if (0) var b = foo(); @@ -1604,24 +1480,24 @@ describe("dce-plugin", () => { ); thePlugin( - "should optimize alternate when empty consequent is replaced with alternate", + "should optimize the alternate when an empty consequent is replaced with the alternate", ` if (baz) { } else { - let foo = 'bar'; + let foo = "bar"; function foobar() {} - console.log('foo' + foo); + console.log("foo" + foo); } `, ` if (!baz) { - console.log('foo' + 'bar'); + console.log("foo" + "bar"); } ` ); thePlugin( - "should transform simple switch statement", + "should transform simple switch statements", ` switch (0) { case 0: foo(); break; @@ -1634,7 +1510,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should NOT optimize when one of the cases is not evaluate-able", + "should bail when one of the cases is not evaluatable", ` switch (a) { case 1: @@ -1668,7 +1544,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should handle defaults", + "should handle `default`s", ` switch (10) { default: @@ -1699,7 +1575,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should predict break statement within blocks", + "should predict break statements within blocks", ` switch (1) { case 1: @@ -1734,7 +1610,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should bail out when break label is above switch's scope", + "should bail out when break label is above the switch’s scope", ` x: switch (1) { case 1: @@ -1756,7 +1632,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should NOT bail out when break label is under switch's scope", + "should NOT bail out when break label is inside the switch’s scope", ` switch (1) { case 1: @@ -1796,7 +1672,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should break correctly when there is a break statement after break", + "should break correctly when there is a repeated break statement", ` switch (0) { case 0: @@ -1832,7 +1708,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should bail out for runtime evaluated if(x) break", + "should bail out for `break` statements inside a non-pure conditional", ` switch (0) { case 0: @@ -1845,7 +1721,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should NOT bail out for runtime evaluated if(x) break inside loop", + "should NOT bail out for `break` statements inside a non-pure conditional inside a loop", ` switch (0) { case 0: @@ -1866,7 +1742,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should optimize While statements", + "should optimize `while` statements", ` while (false) { foo(); @@ -1889,7 +1765,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should optimize For statements", + "should optimize `for` statements", ` for (var i = 0; i < 8; i++) { foo(); @@ -1912,7 +1788,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should optimize dowhile statements", + "should optimize do...while statements", ` do { foo(); @@ -1941,18 +1817,18 @@ describe("dce-plugin", () => { "should not evaluate to false and remove conditional", ` function foo(obj) { - return obj && typeof obj === 'object' ? x() : obj; + return obj && typeof obj === "object" ? x() : obj; } `, ` function foo(obj) { - return obj && typeof obj === 'object' ? x() : obj; + return obj && typeof obj === "object" ? x() : obj; } ` ); thePlugin( - "should extract vars from the removed switch statement", + "should extract `var`s from a removed switch statement", ` switch (0) { case 1: @@ -1975,10 +1851,10 @@ describe("dce-plugin", () => { ); thePlugin( - "should handle side-effecty things in cases", + "should bail on non-pure expressions in cases", ` let i = 0; - let bar = () => console.log('foo'); + let bar = () => console.log("foo"); switch (1) { case ++i: foo(); @@ -1990,7 +1866,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should preserve names in NFEs", + "should preserve names in named function expressions", ` function method() { var removeListeners = function removeListeners() { @@ -2009,8 +1885,9 @@ describe("dce-plugin", () => { ); // https://github.com/babel/babili/issues/130 + // https://github.com/babel/babili/pull/132 thePlugin( - "should not convert expression to expression during replace issue#130", + "should not regress on #130", ` function outer() { const inner = (d) => d.x; @@ -2026,46 +1903,35 @@ describe("dce-plugin", () => { // https://github.com/babel/babili/issues/151 thePlugin( - "should fix issue#151 - array patterns and object patterns", + "should not regress on issue #151 - array patterns and object patterns", ` const me = lyfe => { const [swag] = lyfe; return swag; }; - ` - ); - // https://github.com/babel/babili/issues/151 - thePlugin( - "should fix issue#151 - array patterns and object patterns 2", - ` - const me = lyfe => { + const me2 = lyfe => { const [swag, yolo] = lyfe; return swag && yolo; }; ` ); + // https://github.com/babel/babili/issues/232 thePlugin( - "should fix issue#232 - array patterns and object patterns with non constant init", + "should not regress on issue #232 - array patterns and object patterns with non constant init", ` const a = { lol: input => { - const [hello, world] = input.split('|'); - if (hello === 't' || hello === 'top') { - return 'top'; + const [hello, world] = input.split("|"); + if (hello === "t" || hello === "top") { + return "top"; } - return 'bottom'; + return "bottom"; } }; - ` - ); - // https://github.com/babel/babili/issues/232 - thePlugin( - "should fix issue#232 - array & object patterns with non-constant init", - ` function foo() { const { bar1, bar2 } = baz(); return bar1; @@ -2074,7 +1940,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should preserve variabledeclarations(var) after completion statements", + "should preserve `var` statements after `return`s", ` function foo() { a = 1; @@ -2085,7 +1951,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should NOT preserve variabledeclarations(let) after completion statements", + "should NOT preserve `let` statements after `return`s", ` function foo() { a = 1; @@ -2104,7 +1970,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should not remove var from for..in/for..of statements", + "should not remove `var` from `for...in`/`for...of` statements", ` function foo() { for (var i in x) console.log("foo"); @@ -2114,7 +1980,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should not remove var from for..await statements", + "should not remove `var` from `for await...of` statements", ` async function foo() { for await (var x of y) console.log("bar"); @@ -2145,7 +2011,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should NOT remove fn params for setters", + "should NOT remove function params in setters", ` function foo() { var x = { @@ -2321,22 +2187,12 @@ describe("dce-plugin", () => { ); thePlugin( - "should impure expressions in confidently evaluated if statements", + "should extract impure expressions from if statements with a static condition", ` if (a.b(), true) { foo(); } - `, - ` - a.b(); - foo(); - ` - ); - - thePlugin( - "should extract all necessary things from if statements", - ` if (a.b(), false) { var foo = foo1; foo(); @@ -2349,6 +2205,10 @@ describe("dce-plugin", () => { } `, ` + a.b(); + + foo(); + a.b(); b.c(); @@ -2360,45 +2220,39 @@ describe("dce-plugin", () => { ); thePlugin( - "should not remove vars after return statement", + "should not remove `var` statements after a return statement", ` function f() { return x; var x = 1; } - `, - ` - function f() { - return void 0; - } - ` - ); - thePlugin( - "should not remove vars after return statement #2", - ` - var x = 0; + var y = 0; function f1(){ function f2(){ - return x; + return y; }; return f2(); - var x = 1; + var y = 1; } `, ` - var x = 0; + function f() { + return void 0; + } + + var y = 0; function f1() { return function () { - return x; + return y; }(); - var x = 1; + var y = 1; } ` ); thePlugin( - "should not remove vars after return statement #3", + "should not hoist `var` initializations", ` function foo() { bar = x; @@ -2413,7 +2267,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should deopt for impure tests", + "should bail on impure `if` conditions", ` function foo() { do { @@ -2430,7 +2284,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should handle confident do..while with break statements", + "should handle confident do...while loops with break statements", ` function foo() { do { @@ -2496,7 +2350,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should handle confident do..while with continue statements", + "should handle confident do...while loops with continue statements", ` function foo() { do { @@ -2566,7 +2420,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should remove unnecessary use strict directives", + "should remove unnecessary \"use strict\"; directives", ` function foo() { "use strict"; diff --git a/packages/babel-plugin-minify-flip-comparisons/__tests__/flip-comparisons-test.js b/packages/babel-plugin-minify-flip-comparisons/__tests__/flip-comparisons-test.js index 8c8aa75d9..4483df74f 100644 --- a/packages/babel-plugin-minify-flip-comparisons/__tests__/flip-comparisons-test.js +++ b/packages/babel-plugin-minify-flip-comparisons/__tests__/flip-comparisons-test.js @@ -6,7 +6,7 @@ const thePlugin = require("../../../utils/test-transform")( describe("flip-comparisons", () => { thePlugin( - "should merge two conditionals if the same consequent", + "should merge two conditionals if they share the same consequent", ` x === null ? undefined : x === undefined ? undefined : x ? foo(x) : wat(); `, @@ -36,18 +36,12 @@ describe("flip-comparisons", () => { ); thePlugin( - "should put pures first in binary expressions 2", + "should put pures first in binary expressions", ` a === null; - `, - ` - null === a; - ` - ); - thePlugin( - "should put pures first in binary expressions 3", - ` + a === {}; + function foo() { if (foo !== null) { var bar; @@ -58,6 +52,10 @@ describe("flip-comparisons", () => { } `, ` + null === a; + + ({}) === a; + function foo() { if (null !== foo) { var bar; @@ -70,17 +68,7 @@ describe("flip-comparisons", () => { ); thePlugin( - "should put pures first in binary expressions 2", - ` - a === {}; - `, - ` - ({}) === a; - ` - ); - - thePlugin( - "should put constants first", + "should put constants first in binary expressions", ` x * 100; x + 100; diff --git a/packages/babel-plugin-minify-infinity/__tests__/infinity-test.js b/packages/babel-plugin-minify-infinity/__tests__/infinity-test.js index 06dceeb94..bb99574cf 100644 --- a/packages/babel-plugin-minify-infinity/__tests__/infinity-test.js +++ b/packages/babel-plugin-minify-infinity/__tests__/infinity-test.js @@ -4,9 +4,9 @@ const thePlugin = require("../../../utils/test-transform")( require("../src/index") ); -describe("boolean-plugin", () => { +describe("minify-infinity", () => { thePlugin( - "should convert infinity to division over 0", + "should convert Infinity to division over 0", ` Infinity; `, @@ -16,7 +16,7 @@ describe("boolean-plugin", () => { ); thePlugin( - "should not convert infinity when its a property", + "should not convert Infinity when it’s a property", ` var x = { Infinity: 0 }; x.Infinity; @@ -24,14 +24,14 @@ describe("boolean-plugin", () => { ); thePlugin( - "should not convert infinity if its a assignment expression", + "should not convert Infinity if it’s a assignment expression", ` Infinity = 1; ` ); thePlugin( - "should not convert infinity when its destructed", + "should not convert Infinity when it’s destructed", ` ({ Infinity } = 1); [Infinity] = foo; @@ -40,7 +40,7 @@ describe("boolean-plugin", () => { ); thePlugin( - "should not convert infinity when as a function params", + "should not convert Infinity when as a function params", ` function a(Infinity) {} function a(...Infinity) {} diff --git a/packages/babel-plugin-minify-mangle-names/__tests__/mangle-names-test.js b/packages/babel-plugin-minify-mangle-names/__tests__/mangle-names-test.js index 59adfa805..b6f7c809d 100644 --- a/packages/babel-plugin-minify-mangle-names/__tests__/mangle-names-test.js +++ b/packages/babel-plugin-minify-mangle-names/__tests__/mangle-names-test.js @@ -57,7 +57,7 @@ describe("mangle-names", () => { ); thePlugin( - "should be fine with shadowing", + "should handle shadowing properly", ` var a = 1; function foo() { @@ -117,7 +117,7 @@ describe("mangle-names", () => { ); thePlugin( - "should ignore labels", + "should not mangle labels", ` function foo() { meh: for (;;) { @@ -135,7 +135,7 @@ describe("mangle-names", () => { ); thePlugin( - "should not have labels conflicting with bindings", + "should mangle variables with the same name as labels", ` function foo() { meh: for (;;) { @@ -165,21 +165,7 @@ describe("mangle-names", () => { } return meh; } - `, - ` - function foo() { - var a; - meh: for (;;) { - break meh; - } - return a; - } - ` - ); - thePlugin( - "labels should not shadow bindings 2", - ` function f(a) { try { a: { @@ -189,6 +175,14 @@ describe("mangle-names", () => { } `, ` + function foo() { + var a; + meh: for (;;) { + break meh; + } + return a; + } + function f(b) { try { a: { @@ -212,6 +206,16 @@ describe("mangle-names", () => { } bar(); } + + function foo2() { + (function bar() { + bar(); + return function() { + var bar = wow(); + bar.woo(); + }; + })(); + } `, ` function foo() { @@ -224,24 +228,8 @@ describe("mangle-names", () => { } a(); } - ` - ); - thePlugin( - "should be order independent 2", - ` - function foo() { - (function bar() { - bar(); - return function() { - var bar = wow(); - bar.woo(); - }; - })(); - } - `, - ` - function foo() { + function foo2() { (function a() { a(); return function () { @@ -370,7 +358,7 @@ describe("mangle-names", () => { ); thePlugin( - "should handle global name conflict", + "should handle global name conflicts", ` function e() { function foo() { @@ -390,7 +378,7 @@ describe("mangle-names", () => { ); thePlugin( - "should handle global name", + "should handle global names", ` function foo() { var bar = 1; @@ -449,7 +437,7 @@ describe("mangle-names", () => { ); thePlugin( - "should handle try/catch", + "should handle try...catch statements", ` function xoo() { var e; @@ -846,7 +834,7 @@ describe("mangle-names", () => { ); thePlugin( - "should work with redeclarations", + "should work with redefinitions", ` (function () { var x = y; @@ -1044,7 +1032,7 @@ describe("mangle-names", () => { ); thePlugin( - "should not mangle the name arguments", + "should not mangle the `arguments` variable", ` (function () { var arguments = void 0; @@ -1056,7 +1044,7 @@ describe("mangle-names", () => { ); thePlugin( - "should mangle topLevel when topLevel option is true", + "should mangle top-level variables when topLevel option is true", ` function foo() { if (FOO_ENV === "production") { @@ -1212,7 +1200,7 @@ describe("mangle-names", () => { ); thePlugin( - "should work with if_return optimization changing fn scope", + "should work with if_return optimization changing function scope", ` function foo() { if (x) diff --git a/packages/babel-plugin-minify-numeric-literals/__tests__/numeric-literals-test.js b/packages/babel-plugin-minify-numeric-literals/__tests__/numeric-literals-test.js index 89e74e278..5b931371c 100644 --- a/packages/babel-plugin-minify-numeric-literals/__tests__/numeric-literals-test.js +++ b/packages/babel-plugin-minify-numeric-literals/__tests__/numeric-literals-test.js @@ -6,7 +6,7 @@ const thePlugin = require("../../../utils/test-transform")( describe("numeric-literals", () => { thePlugin( - "should shorten properly", + "should shorten numeric literals properly", ` [10, 100, 1000, 10000, -2, -30000]; [1e3, -1e4, 1e-5, 1.5e12, 1.23456, .1]; diff --git a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js index 42b4f99e9..fa5f0a1f3 100644 --- a/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js +++ b/packages/babel-plugin-minify-simplify/__tests__/simplify-test.js @@ -49,7 +49,7 @@ describe("simplify-plugin", () => { ); thePlugin( - "should turn for loop block to a single statement", + "should turn a for loop block to a single statement", ` for (var x = 0; x < 10; x++) { console.log(x); @@ -61,7 +61,7 @@ describe("simplify-plugin", () => { ); thePlugin( - "should turn block statements to sequence expr", + "should turn block statements into a comma expression", ` for (var x = 0; x < 10; x++) { console.log(x); @@ -74,7 +74,7 @@ describe("simplify-plugin", () => { ); thePlugin( - "should the program into as much sequence exprs", + "should merge lines of code into one comma expression where possible", ` x(); y(); @@ -98,7 +98,7 @@ describe("simplify-plugin", () => { ); thePlugin( - "should turn if to gaurded expression", + "should turn `if` statements into gaurded expressions", ` function foo() { if (x) a(); @@ -112,7 +112,7 @@ describe("simplify-plugin", () => { ); thePlugin( - "should turn if statement to conditional", + "should turn if statements into a ternary", ` function foo() { if (x) a(); @@ -127,7 +127,7 @@ describe("simplify-plugin", () => { ); thePlugin( - "should turn this into a conditional", + "should minify complex `if` statements", ` function foo(a) { if (a && a.b != null) { @@ -138,38 +138,8 @@ describe("simplify-plugin", () => { } return bar(a); } - `, - ` - function foo(a) { - return a && a.b != null ? (a.c-- === 1 && delete a.c, a.b) : bar(a); - } - ` - ); - - thePlugin( - "should turn this into a conditional", - ` - function foo(a) { - if (a && a.b != null) { - if ((a.c--) === 1) { - delete a.c; - } - return a.b; - } - return bar(a); - } - `, - ` - function foo(a) { - return a && a.b != null ? (a.c-- === 1 && delete a.c, a.b) : bar(a); - } - ` - ); - thePlugin( - "should turn this into a conditional", - ` - function foo(a) { + function foo2(a) { if (a) { return a.b; } else { @@ -179,13 +149,17 @@ describe("simplify-plugin", () => { `, ` function foo(a) { + return a && a.b != null ? (a.c-- === 1 && delete a.c, a.b) : bar(a); + } + + function foo2(a) { return a ? a.b : bar(a); } ` ); thePlugin.skip( - "should turn IIFE to negation", + "should convert (function () {...})() into !function () {}()", ` (function() { x(); @@ -204,7 +178,7 @@ describe("simplify-plugin", () => { ); thePlugin( - "should remove the else block if early return", + "should remove the `else` block if there is an early return", ` function foo() { if (1) { @@ -223,7 +197,7 @@ describe("simplify-plugin", () => { ); thePlugin( - "should merge blocks into a return with sequence expr", + "should merge expressions into a comma expression in a `return` statement", ` function foo() { y(); @@ -239,7 +213,7 @@ describe("simplify-plugin", () => { ); thePlugin( - "should merge blocks into a return with sequence expr", + "should merge blocks into a `return` statement with a comma expression", ` function foo() { try { @@ -267,7 +241,7 @@ describe("simplify-plugin", () => { // https://github.com/babel/babili/issues/208 thePlugin( - "should handle empty blocks when merging to sequences", + "should not regresson #208 by handling empty blocks when merging lines into sequences", ` !function () { var x; @@ -284,7 +258,7 @@ describe("simplify-plugin", () => { ); thePlugin( - "should merge expressions into the init part of for", + "should merge expressions into the init part of a `for` loop", ` function foo() { x(); @@ -300,7 +274,7 @@ describe("simplify-plugin", () => { ); thePlugin( - "should merge statements into the init part of for even when there are others", + "should merge statements into the init part of a `for` loop even when there are other expressions there", ` function foo() { x(); @@ -316,7 +290,7 @@ describe("simplify-plugin", () => { ); thePlugin( - "should remove empty returns", + "should remove empty `return` statements", ` function foo() { lol(); diff --git a/packages/babel-plugin-minify-type-constructors/__tests__/type-constructors-test.js b/packages/babel-plugin-minify-type-constructors/__tests__/type-constructors-test.js index d44d22c23..40c15afad 100644 --- a/packages/babel-plugin-minify-type-constructors/__tests__/type-constructors-test.js +++ b/packages/babel-plugin-minify-type-constructors/__tests__/type-constructors-test.js @@ -7,7 +7,7 @@ const thePlugin = require("../../../utils/test-transform")(plugin); describe("type-constructors-plugin", () => { thePlugin( - "should turn Boolean(x) to !!x", + "should turn `Boolean(x)` into `!!x`", ` Boolean(x); `, @@ -17,7 +17,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should turn Number(x) to +x", + "should turn `Number(x)` into `+x`", ` Number(x); `, @@ -27,7 +27,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should turn String(x) to x + ''", + "should turn `String(x)` into `x + ''`", ` String(x); `, @@ -37,7 +37,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should turn Array() to []", + "should turn `Array()` into `[]`", ` Array(); `, @@ -47,7 +47,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should turn new Array() to []", + "should turn `new Array()` into `[]`", ` new Array(); `, @@ -57,7 +57,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should turn Array(nonNumericValue) to [nonNumericValue]", + "should turn `Array(nonNumericValue)` into `[nonNumericValue]`", ` Array("Rome"); Array(false); @@ -83,7 +83,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should turn Array(number) to [,] only if number is <=6", + "should turn `Array(number)` into `[,]` if and only if `number <= 6`", ` Array(0); Array(1); @@ -99,7 +99,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should turn new Array(number) to Array(number) if number is >6", + "should turn `new Array(number)` into `Array(number)` if `number > 6`", ` new Array(6); new Array(7); @@ -111,7 +111,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should turn Array(value, value) to [value, value]", + "should turn `Array(value, value)` into `[value, value]`", ` Array("a", "b"); new Array("0", "1", {}); @@ -125,7 +125,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should turn Object() to {}", + "should turn `Object()` into `{}`", ` var x = Object(); `, @@ -135,7 +135,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should turn new Object() to {}", + "should turn `new Object()` into `{}`", ` var x = new Object(); `, @@ -145,7 +145,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should change Object(null|undefined) to {}", + "should change `Object(null|undefined)` into `{}`", ` [ Object(null), @@ -160,7 +160,7 @@ describe("type-constructors-plugin", () => { // TODO: add Object(Array()) thePlugin( - "should change Object({a:b}) to {a:b}", + "should change `Object({a:b})` into `{a:b}`", ` [ Object({}), @@ -175,7 +175,7 @@ describe("type-constructors-plugin", () => { // TODO: add Object(Array()) thePlugin( - "should change Object([]) to []", + "should change `Object([])` into `[]`", ` [ Object([]), @@ -190,7 +190,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should change Object(localFn) to localFn", + "should change `Object(localFn)` into `localFn`", ` function a() {}; [ @@ -206,7 +206,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "shouldn't change Object(value) for unrecognized values", + "shouldn't change `Object(value)` for unrecognized values", ` [ Object("undefined"), @@ -222,7 +222,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should change new Object(value) to Object(value) for unrecognized values", + "should change `new Object(value)` into `Object(value)` for unrecognized values", ` [ new Object("function"), @@ -238,7 +238,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "should change Object() to ({}) in ambiguous contexts", + "should change `Object()` into `({})` in ambiguous contexts", ` new Object(); var foo = () => Object(); @@ -252,7 +252,7 @@ describe("type-constructors-plugin", () => { ); thePlugin( - "shouldn't change referenced identifiers", + "shouldn't change overridden type constructors", ` (function (Boolean, String, Number, Array, Object) { return Boolean(a), String(b), Number(c), Array(d), Object(d); @@ -266,7 +266,7 @@ describe("type-constructors-plugin", () => { ); // options tests - it("should not transform type for falsy option", () => { + it("should respect the options disabling optomizations", () => { const types = { boolean: "Boolean", number: "Number", @@ -295,7 +295,7 @@ describe("type-constructors-plugin", () => { // https://github.com/babel/babili/issues/206 thePlugin( - "should handle floating point numbers in Array()", + "should handle floating point numbers in `Array()`", ` new Array(-0.01); new Array(-1); diff --git a/packages/babel-plugin-transform-inline-consecutive-adds/__tests__/transform-inline-consecutive-adds-test.js b/packages/babel-plugin-transform-inline-consecutive-adds/__tests__/transform-inline-consecutive-adds-test.js index 5da120d02..f55baa305 100644 --- a/packages/babel-plugin-transform-inline-consecutive-adds/__tests__/transform-inline-consecutive-adds-test.js +++ b/packages/babel-plugin-transform-inline-consecutive-adds/__tests__/transform-inline-consecutive-adds-test.js @@ -6,7 +6,7 @@ const thePlugin = require("../../../utils/test-transform")( describe("transform-inline-consecutive-adds-plugin", () => { thePlugin( - "should collapse simple consecutive", + "should collapse simple consecutive assignments", ` const foo = { z: 3.0 @@ -28,7 +28,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should collapse only up to last ExpressionStatement", + "should collapse only up to the last ExpressionStatement", ` const foo = {}; foo.a = 42; @@ -44,7 +44,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse if lval is nested MemberExpression", + "should not collapse if the lval is a nested MemberExpression", ` const foo = {}; foo.bar.a = 42; @@ -52,7 +52,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse if lval has wrong name", + "should not collapse if the lval is different from the one in hte previous line", ` const foo = {}; bar.a = 42; @@ -60,7 +60,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse if has direct dependency issues", + "should not collapse if the property directly depends on another property", ` const foo = {}; foo.a = function () { @@ -80,7 +80,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse if has indirect dependency issues", + "should not collapse if the property indirectly depends on another property", ` var foo = {}; foo.a = 4; @@ -110,7 +110,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse if has indirect, nested dependency issues", + "should not collapse if the property indirectly depends on another property inside a nested function", ` var foo = {}; foo.a = 4; @@ -163,7 +163,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse computed properties with dependency issues", + "should not collapse computed properties whose key depends on the object", ` var foo = {}; foo[bar()] = 0; @@ -175,7 +175,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse computed properties with circular reference", + "should not collapse computed properties with circular references", ` var foo = {}; foo.bar = foo; @@ -209,7 +209,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should collapse statements for arrays", + "should collapse `Array#push` calls", ` var foo = [1, 2]; foo.push(3, 4), foo.push(5); @@ -221,7 +221,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should collapse statements for sets", + "should collapse `Set#add` calls", ` var foo = new Set(); foo.add(1), foo.add(2); @@ -233,7 +233,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should collapse statements for array-initialized sets", + "should collapse `Set#add` calls with array-initialized sets", ` var foo = new Set([1, 2]); foo.add(3); @@ -244,7 +244,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse statements for array-initialized sets with circular reference", + "should not collapse statements for array-initialized sets with circular references", ` var foo = new Set([1, 2]); foo.add(foo); @@ -265,7 +265,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse array property assignments if long", + "should not collapse array property assignments if it doesn’t make the code shorter", ` var foo = []; foo[10] = 'blah'; @@ -273,7 +273,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse array property assignments if override initial", + "should not collapse array property assignments if they override properties assigned in the inital declaration", ` var foo = [1, 2, 3]; foo[2] = 'blah'; @@ -281,7 +281,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse array property assignments if override dynamic", + "should not collapse array property assignments if they override properties assigned outside of the initial declaration", ` var foo = [1, 2]; foo[2] = 'blah'; @@ -290,7 +290,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse array property assignments if index is float", + "should not collapse array property assignments if the index is a float", ` var foo = []; foo[2.1] = 'blah'; @@ -298,7 +298,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse array property assignments if index is non-int as string", + "should not collapse array property assignments if index is a float written as a string", ` var foo = []; foo['2.1'] = 'blah'; @@ -306,7 +306,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should collapse array property assignments if index is int as string", + "should collapse array property assignments if index is an integer written as string", ` var foo = []; foo['2'] = 'blah'; @@ -317,7 +317,7 @@ describe("transform-inline-consecutive-adds-plugin", () => { ); thePlugin( - "should not collapse array property assignments if it is circular reference", + "should not collapse array property assignments if the rval is a circular reference", ` var foo = []; foo[2] = foo; diff --git a/packages/babel-plugin-transform-member-expression-literals/__tests__/transform-member-expression-literals-test.js b/packages/babel-plugin-transform-member-expression-literals/__tests__/transform-member-expression-literals-test.js index 21d468597..1e0921730 100644 --- a/packages/babel-plugin-transform-member-expression-literals/__tests__/transform-member-expression-literals-test.js +++ b/packages/babel-plugin-transform-member-expression-literals/__tests__/transform-member-expression-literals-test.js @@ -6,7 +6,7 @@ const thePlugin = require("../../../utils/test-transform")( describe("transform-member-expressions-literals-plugin", () => { thePlugin( - "should work with string literals", + "should minify string literals to dot notation", ` foo['bar']; `, @@ -16,7 +16,7 @@ describe("transform-member-expressions-literals-plugin", () => { ); thePlugin( - "should work with numbers", + "should minify numbers as strings to actual numbers", ` foo['1']; `, @@ -26,7 +26,7 @@ describe("transform-member-expressions-literals-plugin", () => { ); thePlugin( - "should not strip necessaary quotes for numeric like things", + "should not strip necessaary quotes for numbers with leading zeroes", ` data['00'] = 5; ` diff --git a/packages/babel-plugin-transform-merge-sibling-variables/__tests__/transform-merge-sibling-variables-test.js b/packages/babel-plugin-transform-merge-sibling-variables/__tests__/transform-merge-sibling-variables-test.js index 53e459b28..8b474d139 100644 --- a/packages/babel-plugin-transform-merge-sibling-variables/__tests__/transform-merge-sibling-variables-test.js +++ b/packages/babel-plugin-transform-merge-sibling-variables/__tests__/transform-merge-sibling-variables-test.js @@ -6,7 +6,7 @@ const thePlugin = require("../../../utils/test-transform")( describe("transform-merge-sibling-variables-plugin", () => { thePlugin( - "concat vars", + "should concat `var` declarations", ` var i = 0; var x = 0; @@ -20,7 +20,7 @@ describe("transform-merge-sibling-variables-plugin", () => { ); thePlugin( - "concat vars in for loops", + "should concat `var` declarations in for loops", ` var i = 0; var j = 0; @@ -32,7 +32,7 @@ describe("transform-merge-sibling-variables-plugin", () => { ); thePlugin( - "don't concat block-scoped variables in for loops", + "should not concat block-scoped variables in for loops", ` let i = 0; for (let x = 0; x < 10; x++) console.log(i + x); @@ -40,7 +40,7 @@ describe("transform-merge-sibling-variables-plugin", () => { ); thePlugin( - "don't concat constants in for loops", + "should not concat constants in for loops", ` const j = 0; for (const x = 0;;) console.log(j + x); @@ -48,7 +48,7 @@ describe("transform-merge-sibling-variables-plugin", () => { ); thePlugin( - "concat block-scoped vars next to, but not into for loops", + "should concat block-scoped variable declarations next to, but not into, for loops", ` let i = 0; let y = 0; @@ -63,7 +63,7 @@ describe("transform-merge-sibling-variables-plugin", () => { ); thePlugin( - "lift var declarations to loop intializer", + "lift `var` declarations to the loop intializer", ` for (var i = 0; i < 0; i++) { var j = jj(); @@ -79,7 +79,7 @@ describe("transform-merge-sibling-variables-plugin", () => { ); thePlugin( - "lift let declarations to loop intializer", + "lift `let` declarations to the loop intializer", ` for (let i = 0; i < 0; i++) { let j = jj(); @@ -93,7 +93,7 @@ describe("transform-merge-sibling-variables-plugin", () => { ); thePlugin( - "dont lift declarations on object/array pattern", + "should not lift declarations from array or object destructuring asignments", ` for (var i = 0; i < 0; i++) { var [j] = jj(); @@ -105,7 +105,7 @@ describe("transform-merge-sibling-variables-plugin", () => { ); thePlugin( - "dont lift declarations when no body is present", + "should not lift declarations when no loop initializer is present", ` for (;;) {} for (;;) var i = 0; @@ -113,7 +113,7 @@ describe("transform-merge-sibling-variables-plugin", () => { ); thePlugin( - "dont lift when the declarations are of different kind", + "should not lift when the declarations are of different types", ` for (let i = 0; i < 0; i++) { var i = 0; @@ -122,7 +122,7 @@ describe("transform-merge-sibling-variables-plugin", () => { ); thePlugin( - "dont lift when the declarations are not initialized", + "should not lift when the declarations are not initialized", ` for (var i = 0;;) { var i; @@ -131,7 +131,7 @@ describe("transform-merge-sibling-variables-plugin", () => { ); thePlugin( - "dont lift when there are multiple declarations", + "should not lift when there are multiple declarations", ` for (var i = 0; i < 0; i++) { var i = 0, k = 0; diff --git a/packages/babel-plugin-transform-minify-booleans/__tests__/booleans-test.js b/packages/babel-plugin-transform-minify-booleans/__tests__/booleans-test.js index cfcef4212..a998b9440 100644 --- a/packages/babel-plugin-transform-minify-booleans/__tests__/booleans-test.js +++ b/packages/babel-plugin-transform-minify-booleans/__tests__/booleans-test.js @@ -6,7 +6,7 @@ const thePlugin = require("../../../utils/test-transform")( describe("boolean-plugin", () => { thePlugin( - "should shorten bool", + "should shorten `true` and `false` to `!0` and `!1`, repsectively", ` true; false; `, diff --git a/packages/babel-plugin-transform-node-env-inline/__tests__/node-env-inline-test.js b/packages/babel-plugin-transform-node-env-inline/__tests__/node-env-inline-test.js index 830cecf3e..f463fcb3a 100644 --- a/packages/babel-plugin-transform-node-env-inline/__tests__/node-env-inline-test.js +++ b/packages/babel-plugin-transform-node-env-inline/__tests__/node-env-inline-test.js @@ -12,7 +12,7 @@ describe("node-env-inline-plugin", () => { }); thePlugin( - "should inline", + "should inline checks for `process.env.NODE_ENV = 'foo'`", ` process.env.NODE_ENV === "development"; `, diff --git a/packages/babel-plugin-transform-property-literals/__tests__/transform-property-literals-test.js b/packages/babel-plugin-transform-property-literals/__tests__/transform-property-literals-test.js index 51f242309..db37b72c9 100644 --- a/packages/babel-plugin-transform-property-literals/__tests__/transform-property-literals-test.js +++ b/packages/babel-plugin-transform-property-literals/__tests__/transform-property-literals-test.js @@ -26,7 +26,7 @@ describe("transform-property-literals-plugin", () => { ); thePlugin( - "should not strip necessaary quotes for numeric like things", + "should not strip necessaary quotes for numbers with leading zeroes", ` var data = { "00": 1, @@ -35,6 +35,8 @@ describe("transform-property-literals-plugin", () => { ` ); + // FIXME: The test name states that no transformation should take place, + // but the actual test specifies that the quotes should be stripped. thePlugin( "should not transform invalid identifiers", ` @@ -79,6 +81,8 @@ describe("transform-property-literals-plugin", () => { ` ); + // FIXME: The test name states that the property names should be transformed, + // but the `12e34` one isn’t transformed in the test thePlugin( "should transform valid ES5 unicodes as property names", ` diff --git a/packages/babel-plugin-transform-regexp-constructors/__tests__/transform-regexp-constructors-test.js b/packages/babel-plugin-transform-regexp-constructors/__tests__/transform-regexp-constructors-test.js index d9acc05e4..c46ff75cf 100644 --- a/packages/babel-plugin-transform-regexp-constructors/__tests__/transform-regexp-constructors-test.js +++ b/packages/babel-plugin-transform-regexp-constructors/__tests__/transform-regexp-constructors-test.js @@ -16,7 +16,7 @@ describe("transform-regexp-constructors-plugin", () => { ); thePlugin( - "should transform newlines fine", + "should transform `\n` properly", String.raw` var x = new RegExp('\\n'); `, @@ -26,7 +26,7 @@ describe("transform-regexp-constructors-plugin", () => { ); thePlugin( - "should transform unicode newlines fine", + "should transform unicode newlines properly", String.raw` var x = new RegExp('\u2028\u2029'); `, @@ -83,7 +83,7 @@ describe("transform-regexp-constructors-plugin", () => { ); thePlugin( - "should transform empty RegExp constructor", + "should transform RegExp constructor with no arguments into `/(?:)/`", ` var x = new RegExp(); `, @@ -93,7 +93,7 @@ describe("transform-regexp-constructors-plugin", () => { ); thePlugin( - "should transform RegExp constructor with empty string", + "should transform RegExp constructor with an empty string argument into `/(?:)/`", ` var x = new RegExp(''); `, @@ -103,18 +103,18 @@ describe("transform-regexp-constructors-plugin", () => { ); thePlugin( - "should resolve expressions and const references", - ` + "should resolve expressions and const references in the constructor", + String.raw` const foo = "ab+"; - const bar = "c\\\\w"; + const bar = "c\\w"; const flags = "g"; const ret = new RegExp(foo + bar + "d", flags); `, - ` + String.raw` const foo = "ab+"; - const bar = "c\\\\w"; + const bar = "c\\w"; const flags = "g"; - const ret = /ab+c\\wd/g; + const ret = /ab+c\wd/g; ` ); diff --git a/packages/babel-plugin-transform-remove-console/__tests__/remove-console-test.js b/packages/babel-plugin-transform-remove-console/__tests__/remove-console-test.js index 054c43111..7d08317aa 100644 --- a/packages/babel-plugin-transform-remove-console/__tests__/remove-console-test.js +++ b/packages/babel-plugin-transform-remove-console/__tests__/remove-console-test.js @@ -6,7 +6,7 @@ const thePlugin = require("../../../utils/test-transform")( describe("remove-console-plugin", () => { thePlugin( - "statement-nested", + "should remove `console.*` calls in nested statements", ` function foo() { console.log("foo"); @@ -21,7 +21,7 @@ describe("remove-console-plugin", () => { ); thePlugin( - "expression-nested", + "should remove `console.*` calls in nested expressions", ` function foo() { true && console.log("foo"); @@ -37,7 +37,7 @@ describe("remove-console-plugin", () => { ); thePlugin( - "expression-top-level", + "should remove `console.*` calls in top-level expressions", ` true && console.log("foo"); blah(); @@ -49,7 +49,7 @@ describe("remove-console-plugin", () => { ); thePlugin( - "statement-top-level", + "should remove `console.*` calls in top-level statements", ` console.log("foo"); blah(); @@ -60,7 +60,7 @@ describe("remove-console-plugin", () => { ); thePlugin( - "statement no block", + "should remove `console.*` calls in statements not surrounded by a block", ` if (blah) console.log(blah); for (;;) console.log(blah); @@ -80,7 +80,7 @@ describe("remove-console-plugin", () => { ); thePlugin( - "should remove console.* assignments to other variables", + "should remove `console.*` assignments to other variables and replace them with empty functions", ` const a = console.log; a(); @@ -108,7 +108,7 @@ describe("remove-console-plugin", () => { ); thePlugin( - "should NOT remove local bindings of name console", + "should NOT remove local bindings of the name `console`", ` function foo(console) { console.foo("hi"); @@ -125,7 +125,7 @@ describe("remove-console-plugin", () => { ); thePlugin( - "should convert assigments to no-op", + "should convert assigments from `console` functions to a no-op", ` function foo() { console.foo = function foo() { diff --git a/packages/babel-plugin-transform-remove-debugger/__tests__/remove-debugger-test.js b/packages/babel-plugin-transform-remove-debugger/__tests__/remove-debugger-test.js index 5370e1e84..135b1fe5d 100644 --- a/packages/babel-plugin-transform-remove-debugger/__tests__/remove-debugger-test.js +++ b/packages/babel-plugin-transform-remove-debugger/__tests__/remove-debugger-test.js @@ -6,7 +6,7 @@ const thePlugin = require("../../../utils/test-transform")( describe("remove-debugger-plugin", () => { thePlugin( - "should remove debugger", + "should remove `debugger` statements", ` debugger; `, @@ -15,7 +15,7 @@ describe("remove-debugger-plugin", () => { ); thePlugin( - "should remove debugger only", + "should not remove non-`debugger` statements on the same line as the `debugger` statement", ` debugger; 1; `, @@ -25,7 +25,7 @@ describe("remove-debugger-plugin", () => { ); thePlugin( - "statement no block", + "should add an empty block (`{}`) when the `debugger` statement was the only child of the block", ` if (blah) debugger; for (;;) debugger; diff --git a/packages/babel-plugin-transform-simplify-comparison-operators/__tests__/strict-equals-test.js b/packages/babel-plugin-transform-simplify-comparison-operators/__tests__/strict-equals-test.js index 0d7b734e3..82cce3f10 100644 --- a/packages/babel-plugin-transform-simplify-comparison-operators/__tests__/strict-equals-test.js +++ b/packages/babel-plugin-transform-simplify-comparison-operators/__tests__/strict-equals-test.js @@ -6,7 +6,7 @@ const thePlugin = require("../../../utils/test-transform")( describe("simplify-comparison-operators-plugin", () => { thePlugin( - "should simplify comparison", + "should simplify `typeof` comparisons", ` 'function' === typeof a; `, @@ -16,53 +16,39 @@ describe("simplify-comparison-operators-plugin", () => { ); thePlugin( - "should simplify comparison operations", + "should simplify `== null` comparison operations where possible", ` null === null; - `, - ` - null == null; - ` - ); - - thePlugin( - "should comparison operations 2", - ` var x = null; x === null; `, ` + null == null; var x = null; x == null; ` ); - thePlugin( - "should not simplify comparison", - ` - var x; - x === null; - ` - ); thePlugin( - "should not simplify comparison 2", + "should not simplify comparisons where losing the third = would change the result", ` var x; + x === null; if (wow) x = foo(); x === null; ` ); thePlugin( - "should not simplify comparison if already simplified", + "should not simplify comparison if it is already simplified", ` typeof 1 == "number"; ` ); thePlugin( - "should not simplify comparison if not equality check", + "should not simplify comparison if it is not an equality check", ` a > b; ` diff --git a/packages/babel-plugin-transform-undefined-to-void/__tests__/undefined-test.js b/packages/babel-plugin-transform-undefined-to-void/__tests__/undefined-test.js index db1e960ec..2791c15a5 100644 --- a/packages/babel-plugin-transform-undefined-to-void/__tests__/undefined-test.js +++ b/packages/babel-plugin-transform-undefined-to-void/__tests__/undefined-test.js @@ -6,7 +6,7 @@ const thePlugin = require("../../../utils/test-transform")( describe("undefined-plugin", () => { thePlugin( - "should turn undefined into void 0", + "should turn `undefined` into `void 0`", ` var foo;foo === undefined; `, @@ -16,7 +16,7 @@ describe("undefined-plugin", () => { ); thePlugin( - "should turn undefined into void 0 in a MemberExpression", + "should turn `undefined` into `void 0` in a MemberExpression", ` var foo;foo === undefined.foo; `, From 97a53cdd38b1dd179ff282b878ea597dead6906e Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Thu, 29 Jun 2017 13:10:43 -0400 Subject: [PATCH 3/4] Fix build --- .../__tests__/dead-code-elimination-test.js | 24 ++++--------------- .../__tests__/strict-equals-test.js | 1 - utils/test-transform.js | 2 +- 3 files changed, 5 insertions(+), 22 deletions(-) diff --git a/packages/babel-plugin-minify-dead-code-elimination/__tests__/dead-code-elimination-test.js b/packages/babel-plugin-minify-dead-code-elimination/__tests__/dead-code-elimination-test.js index 5b270e870..cb42baadd 100644 --- a/packages/babel-plugin-minify-dead-code-elimination/__tests__/dead-code-elimination-test.js +++ b/packages/babel-plugin-minify-dead-code-elimination/__tests__/dead-code-elimination-test.js @@ -6,21 +6,6 @@ const deadcode = require("../src/index"); const simplify = require("../../babel-plugin-minify-simplify/src/index"); const thePlugin = require("../../../utils/test-transform")(deadcode); -function transform(code, options, babelOpts) { - return babel - .transform( - code, - Object.assign( - {}, - { - plugins: [[deadcode, options]] - }, - babelOpts - ) - ) - .code.trim(); -} - function transformWithSimplify(code) { return babel.transform(code, { plugins: [deadcode, simplify] @@ -706,7 +691,8 @@ describe("dce-plugin", () => { foo(); } - `); + ` + ); thePlugin( "should evaluate conditional expressions", @@ -1008,7 +994,7 @@ describe("dce-plugin", () => { thePlugin( "should eval the following to false", ` - function bar () { + function bar() { var x = foo || "boo"; bar = x === "wow" ? " " + z : ""; } @@ -1917,7 +1903,6 @@ describe("dce-plugin", () => { ` ); - // https://github.com/babel/babili/issues/232 thePlugin( "should not regress on issue #232 - array patterns and object patterns with non constant init", @@ -2208,7 +2193,6 @@ describe("dce-plugin", () => { a.b(); foo(); - a.b(); b.c(); @@ -2420,7 +2404,7 @@ describe("dce-plugin", () => { ); thePlugin( - "should remove unnecessary \"use strict\"; directives", + 'should remove unnecessary "use strict"; directives', ` function foo() { "use strict"; diff --git a/packages/babel-plugin-transform-simplify-comparison-operators/__tests__/strict-equals-test.js b/packages/babel-plugin-transform-simplify-comparison-operators/__tests__/strict-equals-test.js index 82cce3f10..3e91533e3 100644 --- a/packages/babel-plugin-transform-simplify-comparison-operators/__tests__/strict-equals-test.js +++ b/packages/babel-plugin-transform-simplify-comparison-operators/__tests__/strict-equals-test.js @@ -29,7 +29,6 @@ describe("simplify-comparison-operators-plugin", () => { ` ); - thePlugin( "should not simplify comparisons where losing the third = would change the result", ` diff --git a/utils/test-transform.js b/utils/test-transform.js index 645757a7c..a12c84152 100644 --- a/utils/test-transform.js +++ b/utils/test-transform.js @@ -43,7 +43,7 @@ function makeTester( }); }; thePlugin.skip = name => it.skip(name); - if (!excludeKeys.includes("inEachLine")) { + if (excludeKeys.indexOf("inEachLine") === -1) { thePlugin.inEachLine = makeTester( plugins, opts, From 0ef0821085e8e58939a73f0ef809e2a158959876 Mon Sep 17 00:00:00 2001 From: Jed Fox Date: Thu, 29 Jun 2017 17:49:02 -0400 Subject: [PATCH 4/4] Add support for thePlugin.only --- utils/test-transform.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/utils/test-transform.js b/utils/test-transform.js index a12c84152..318706b83 100644 --- a/utils/test-transform.js +++ b/utils/test-transform.js @@ -9,7 +9,7 @@ function _transform(source, options) { function makeTester( plugins, opts, - { transform = _transform, check }, + { transform = _transform, check, test = it }, excludeKeys = [] ) { if (!Array.isArray(plugins)) { @@ -26,7 +26,7 @@ function makeTester( opts, babelOpts ); - it(name, () => { + test(name, () => { const transformed = transform(source, options); try { check({ @@ -42,12 +42,13 @@ function makeTester( } }); }; - thePlugin.skip = name => it.skip(name); + thePlugin.skip = name => test.skip(name); if (excludeKeys.indexOf("inEachLine") === -1) { thePlugin.inEachLine = makeTester( plugins, opts, { + test, transform(source, options) { return unpad(source) .split("\n") @@ -59,6 +60,18 @@ function makeTester( excludeKeys.concat("inEachLine") ); } + if (excludeKeys.indexOf("only") === -1) { + thePlugin.only = makeTester( + plugins, + opts, + { + test: test.only, + transform, + check + }, + excludeKeys.concat("only") + ); + } return thePlugin; }