From 92a159d939c1cb93fd372c2fd878f01b7dd522ca Mon Sep 17 00:00:00 2001 From: Joe Haddad Date: Wed, 20 May 2020 11:57:18 -0400 Subject: [PATCH] Correctly eliminate destructuring assignment (#13144) This eliminates code referenced via destructuring assignment, as reported by @styfle. --- .../build/babel/plugins/next-ssg-transform.ts | 76 +++++++++++++++---- .../babel-plugin-next-ssg-transform.test.js | 24 ++++++ 2 files changed, 87 insertions(+), 13 deletions(-) diff --git a/packages/next/build/babel/plugins/next-ssg-transform.ts b/packages/next/build/babel/plugins/next-ssg-transform.ts index cea149d7cd..9bdd35ad73 100644 --- a/packages/next/build/babel/plugins/next-ssg-transform.ts +++ b/packages/next/build/babel/plugins/next-ssg-transform.ts @@ -189,13 +189,33 @@ export default function nextTransformSsg({ path.traverse( { VariableDeclarator(path, state) { - if (path.node.id.type !== 'Identifier') { - return - } + if (path.node.id.type === 'Identifier') { + const local = path.get('id') as NodePath< + BabelTypes.Identifier + > + if (isIdentifierReferenced(local)) { + state.refs.add(local) + } + } else if (path.node.id.type === 'ObjectPattern') { + const pattern = path.get('id') as NodePath< + BabelTypes.ObjectPattern + > - const local = path.get('id') as NodePath - if (isIdentifierReferenced(local)) { - state.refs.add(local) + const properties = pattern.get('properties') + properties.forEach((p) => { + const local = p.get( + p.node.type === 'ObjectProperty' + ? 'value' + : p.node.type === 'RestElement' + ? 'argument' + : (function () { + throw new Error('invariant') + })() + ) as NodePath + if (isIdentifierReferenced(local)) { + state.refs.add(local) + } + }) } }, FunctionDeclaration: markFunction, @@ -319,14 +339,44 @@ export default function nextTransformSsg({ path.traverse({ // eslint-disable-next-line no-loop-func VariableDeclarator(path) { - if (path.node.id.type !== 'Identifier') { - return - } + if (path.node.id.type === 'Identifier') { + const local = path.get('id') as NodePath< + BabelTypes.Identifier + > + if (refs.has(local) && !isIdentifierReferenced(local)) { + ++count + path.remove() + } + } else if (path.node.id.type === 'ObjectPattern') { + const pattern = path.get('id') as NodePath< + BabelTypes.ObjectPattern + > - const local = path.get('id') as NodePath - if (refs.has(local) && !isIdentifierReferenced(local)) { - ++count - path.remove() + const beforeCount = count + const properties = pattern.get('properties') + properties.forEach((p) => { + const local = p.get( + p.node.type === 'ObjectProperty' + ? 'value' + : p.node.type === 'RestElement' + ? 'argument' + : (function () { + throw new Error('invariant') + })() + ) as NodePath + + if (refs.has(local) && !isIdentifierReferenced(local)) { + ++count + p.remove() + } + }) + + if ( + beforeCount !== count && + pattern.get('properties').length < 1 + ) { + path.remove() + } } }, FunctionDeclaration: sweepFunction, diff --git a/test/unit/babel-plugin-next-ssg-transform.test.js b/test/unit/babel-plugin-next-ssg-transform.test.js index 7acba93216..a81c6f358c 100644 --- a/test/unit/babel-plugin-next-ssg-transform.test.js +++ b/test/unit/babel-plugin-next-ssg-transform.test.js @@ -452,5 +452,29 @@ describe('babel plugin (next-ssg-transform)', () => { `"export var __N_SSG=true;export default function Home(){return __jsx(\\"div\\",null);}"` ) }) + + it('destructuring assignment (object)', () => { + const output = babel(trim` + import fs from 'fs'; + import other from 'other'; + + const {readFile, readdir, access: foo} = fs.promises; + const {a,b, cat: bar,...rem} = other; + + export async function getStaticProps() { + readFile; + readdir; + foo; + b; + cat; + rem; + } + export default function Home() { return
; } + `) + + expect(output).toMatchInlineSnapshot( + `"import other from'other';const{a,cat:bar}=other;export var __N_SSG=true;export default function Home(){return __jsx(\\"div\\",null);}"` + ) + }) }) })