From 01720715fd626374e5782c5e303a70f07698f4fa Mon Sep 17 00:00:00 2001 From: Federico Brigante Date: Sun, 10 Jul 2016 15:36:47 +0700 Subject: [PATCH] Transform: Object() -> {} --- .../__tests__/type-constructors-test.js | 80 +++++++++++++++++++ .../package.json | 4 +- .../src/index.js | 47 +++++++++++ 3 files changed, 130 insertions(+), 1 deletion(-) 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 e2c425725..1bbd38f5a 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 @@ -101,6 +101,86 @@ describe("type-constructors-plugin", () => { expect(transform(source)).toBe(expected); }); + + it("should turn Object() to {}", () => { + const source = "var x = Object();"; + const expected = "var x = {};"; + expect(transform(source)).toBe(expected); + }); + + it("should turn new Object() to {}", () => { + const source = "var x = new Object();"; + const expected = "var x = {};"; + expect(transform(source)).toBe(expected); + }); + + it("should change Object(null|undefined|{}) to {}", () => { + const source = unpad(` + [ + Object(null), + Object(undefined), + new Object(void 0), + Object({}) + ] + `); + const expected = "[{}, {}, {}, {}];"; + expect(transform(source)).toBe(expected); + }); + + 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); + }); + + 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); + }); + + it("shouldn't change Object(value) for unrecognized values", () => { + const source = unpad(` + [ + Object("undefined"), + Object(nulled), + Object(false) + ] + `); + const expected = "[Object(\"undefined\"), Object(nulled), Object(false)];"; + expect(transform(source)).toBe(expected); + }); + + it("should change new Object(value) to Object(value) for unrecognized values", () => { + const source = unpad(` + [ + new Object("function"), + new Object(Symbol), + new Object(Array), + new Object(true) + ] + `); + const expected = "[Object(\"function\"), Object(Symbol), Object(Array), Object(true)];"; + expect(transform(source)).toBe(expected); + }); + it("shouldn't change referenced identifiers", () => { const source = unpad(` (function (Boolean, String, Number, Array) { diff --git a/packages/babel-plugin-minify-type-constructors/package.json b/packages/babel-plugin-minify-type-constructors/package.json index e25327757..85018577e 100644 --- a/packages/babel-plugin-minify-type-constructors/package.json +++ b/packages/babel-plugin-minify-type-constructors/package.json @@ -11,6 +11,8 @@ "keywords": [ "babel-plugin" ], - "dependencies": {}, + "dependencies": { + "babel-helper-is-void-0": "^0.0.0" + }, "devDependencies": {} } diff --git a/packages/babel-plugin-minify-type-constructors/src/index.js b/packages/babel-plugin-minify-type-constructors/src/index.js index 35b8c5ee8..177d57a4d 100644 --- a/packages/babel-plugin-minify-type-constructors/src/index.js +++ b/packages/babel-plugin-minify-type-constructors/src/index.js @@ -26,6 +26,43 @@ function replaceArray(t, path) { } } +function replaceObject(t, path) { + const { node } = path; + if (t.isIdentifier(node.callee, { name: "Object" }) && + !path.scope.getBinding("Object")) { + + const isVoid0 = require("babel-helper-is-void-0")(t); + const arg = node.arguments[0]; + const binding = arg && t.isIdentifier(arg) && path.scope.getBinding(arg.name); + + // Object() -> {} + if (node.arguments.length === 0) { + path.replaceWith(t.objectExpression([])); + + // Object([]) -> [] + } else if (arg.type === "ArrayExpression" || + t.isFunctionExpression(arg)) { + path.replaceWith(arg); + + // Object(null) -> {} + } else if (isVoid0(arg) || + arg.name === "undefined" || + arg.type === "NullLiteral" || + arg.type === "ObjectExpression" && arg.properties.length === 0) { + path.replaceWith(t.objectExpression([])); + + // Object(localFn) -> localFn + } else if (binding && binding.path.isFunction()) { + path.replaceWith(arg); + + // new Object(a) -> Object(a) + } else if (node.type === "NewExpression") { + path.replaceWith(t.callExpression(node.callee, node.arguments)); + } + return true; + } +} + module.exports = function({ types: t }) { return { visitor: { @@ -60,12 +97,22 @@ module.exports = function({ types: t }) { if (replaceArray(t, path)) { return; } + + // Object() -> {} + if (replaceObject(t, path)) { + return; + } }, NewExpression(path) { // Array() -> [] if (replaceArray(t, path)) { return; } + + // Object() -> {} + if (replaceObject(t, path)) { + return; + } }, }, };