From 7b0010514e2afc7cfe63efde97e3602ada0d5e56 Mon Sep 17 00:00:00 2001 From: Boopathi Rajaa Date: Mon, 25 Sep 2017 14:30:03 +0200 Subject: [PATCH] Fix folding array literals - bail on spread element + Fixes #695 + Fixes #628 + Related #610 --- .../__tests__/constant-folding-test.js | 8 +++++ .../src/index.js | 32 ++++++++++++------- .../src/replacements.js | 13 ++++++-- 3 files changed, 39 insertions(+), 14 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 7e7178ba2..408738f40 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 @@ -246,4 +246,12 @@ describe("constant-folding-plugin", () => { } ` ); + + thePlugin( + "should not fold array literals with spread element", + ` + [...bar].reverse(); + [...foo].join("a"); + ` + ); }); diff --git a/packages/babel-plugin-minify-constant-folding/src/index.js b/packages/babel-plugin-minify-constant-folding/src/index.js index 8b15665b1..02fd8c9c1 100644 --- a/packages/babel-plugin-minify-constant-folding/src/index.js +++ b/packages/babel-plugin-minify-constant-folding/src/index.js @@ -20,18 +20,17 @@ function getName(member) { function swap(path, member, handlers, ...args) { const key = getName(member.node); - if (key === undefined) return; - let handler = handlers[key]; - if ( - typeof handler !== "function" || - !Object.hasOwnProperty.call(handlers, key) - ) { - if (typeof handlers[FALLBACK_HANDLER] === "function") { - handler = handlers[FALLBACK_HANDLER].bind(member.get("object"), key); - } else { - return false; - } + if (key === void 0) return false; + + let handler; + if (hop(handlers, key) && typeof handlers[key] === "function") { + handler = handlers[key]; + } else if (typeof handlers[FALLBACK_HANDLER] === "function") { + handler = handlers[FALLBACK_HANDLER].bind(member.get("object"), key); + } else { + return false; } + const replacement = handler.apply(member.get("object"), args); if (replacement) { path.replaceWith(replacement); @@ -172,6 +171,13 @@ module.exports = babel => { if (t.isMemberExpression(member)) { const helpers = replacements[member.node.object.type]; if (!helpers || !helpers.calls) return; + // find if the input can be constant folded + if ( + typeof helpers.canReplace === "function" && + !helpers.canReplace.call(member.get("object")) + ) { + return; + } swap(path, member, helpers.calls, ...node.arguments); } }, @@ -184,3 +190,7 @@ module.exports = babel => { } }; }; + +function hop(o, key) { + return Object.prototype.hasOwnProperty.call(o, key); +} diff --git a/packages/babel-plugin-minify-constant-folding/src/replacements.js b/packages/babel-plugin-minify-constant-folding/src/replacements.js index ae52887d4..db0207786 100644 --- a/packages/babel-plugin-minify-constant-folding/src/replacements.js +++ b/packages/babel-plugin-minify-constant-folding/src/replacements.js @@ -19,17 +19,24 @@ module.exports = ({ types: t }) => { }; } + function hasSpread(node) { + return node.elements.some(el => t.isSpreadElement(el)); + } + return { ArrayExpression: { + canReplace() { + return !hasSpread(this.node); + }, members: { length() { - if (this.node.elements.some(el => t.isSpreadElement(el))) { + if (hasSpread(this.node)) { return; } return t.numericLiteral(this.node.elements.length); }, [FALLBACK_HANDLER](i) { - if (this.node.elements.some(el => t.isSpreadElement(el))) { + if (hasSpread(this.node)) { return; } if (typeof i === "number" || i.match(/^\d+$/)) { @@ -51,7 +58,7 @@ module.exports = ({ types: t }) => { return evaled.value; }) .join(sep.value); - return bad ? undefined : t.stringLiteral(str); + return bad ? void 0 : t.stringLiteral(str); }, push(...args) { return t.numericLiteral(this.node.elements.length + args.length);