Skip to content

Commit 9db0b61

Browse files
authored
fix(ssr): rewrite computed key of destructing parameter (#23307)
1 parent 1fb8afe commit 9db0b61

2 files changed

Lines changed: 59 additions & 32 deletions

File tree

packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,63 @@ function c({ _ = bar() + foo() }) {}
777777
`)
778778
})
779779

780+
// #23232
781+
test('function argument destructure with a default parameter', async () => {
782+
expect(
783+
await ssrTransformSimpleCode(
784+
`
785+
import { key } from 'foo'
786+
function noParameterDefault({ [key]: value = null }) {}
787+
function declaration({ [key]: value = null } = {}) {}
788+
function compound({ [key.name]: value } = {}) {}
789+
const arrow = ({ [key]: value = null } = {}) => {}
790+
function nested({ a: { [key]: value } = {} } = {}) {}
791+
function array([{ [key]: value } = {}] = []) {}
792+
class Foo { method({ [key]: value } = {}) {} }
793+
`,
794+
),
795+
).toMatchInlineSnapshot(`
796+
"const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["key"]});
797+
798+
799+
function noParameterDefault({ [__vite_ssr_import_0__.key]: value = null }) {}
800+
function declaration({ [__vite_ssr_import_0__.key]: value = null } = {}) {}
801+
function compound({ [__vite_ssr_import_0__.key.name]: value } = {}) {}
802+
const arrow = ({ [__vite_ssr_import_0__.key]: value = null } = {}) => {};
803+
function nested({ a: { [__vite_ssr_import_0__.key]: value } = {} } = {}) {}
804+
function array([{ [__vite_ssr_import_0__.key]: value } = {}] = []) {}
805+
class Foo { method({ [__vite_ssr_import_0__.key]: value } = {}) {} }
806+
"
807+
`)
808+
})
809+
810+
test('function argument destructure with a default parameter preserves shadowing', async () => {
811+
expect(
812+
await ssrTransformSimpleCode(
813+
`
814+
import { key } from 'foo'
815+
function shorthand({ key } = {}) { return key }
816+
function aliased({ prop: key } = {}) { return key }
817+
function defaulted({ key = 'default' } = {}) { return key }
818+
function array([key] = []) { return key }
819+
function plain(key) { return key }
820+
console.log(key)
821+
`,
822+
),
823+
).toMatchInlineSnapshot(`
824+
"const __vite_ssr_import_0__ = await __vite_ssr_import__("foo", {"importedNames":["key"]});
825+
826+
827+
function shorthand({ key } = {}) { return key }
828+
function aliased({ prop: key } = {}) { return key }
829+
function defaulted({ key = 'default' } = {}) { return key }
830+
function array([key] = []) { return key }
831+
function plain(key) { return key }
832+
console.log((0,__vite_ssr_import_0__.key))
833+
"
834+
`)
835+
})
836+
780837
test('object destructure alias', async () => {
781838
expect(
782839
await ssrTransformSimpleCode(

packages/vite/src/node/ssr/ssrTransform.ts

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -575,38 +575,8 @@ function walk(
575575
if (node.type === 'FunctionExpression' && node.id) {
576576
setScope(node, node.id.name)
577577
}
578-
// walk function expressions and add its arguments to known identifiers
579-
// so that we don't prefix them
580-
node.params.forEach((p) => {
581-
if (p.type === 'ObjectPattern' || p.type === 'ArrayPattern') {
582-
handlePattern(p, node)
583-
return
584-
}
585-
;(eswalk as any)(p.type === 'AssignmentPattern' ? p.left : p, {
586-
enter(child: ESTree.Node, parent: ESTree.Node | undefined) {
587-
// skip params default value of destructure
588-
if (
589-
parent?.type === 'AssignmentPattern' &&
590-
parent.right === child
591-
) {
592-
return this.skip()
593-
}
594-
if (child.type !== 'Identifier') return
595-
// do not record as scope variable if is a destructuring keyword
596-
if (isStaticPropertyKey(child, parent)) return
597-
// do not record if this is a default value
598-
// assignment of a destructuring variable
599-
if (
600-
(parent?.type === 'TemplateLiteral' &&
601-
parent.expressions.includes(child as ESTree.Expression)) ||
602-
(parent?.type === 'CallExpression' && parent.callee === child)
603-
) {
604-
return
605-
}
606-
setScope(node, child.name)
607-
},
608-
})
609-
})
578+
// add function arguments to known identifiers so that we don't prefix them
579+
node.params.forEach((p) => handlePattern(p, node))
610580
} else if (node.type === 'ClassDeclaration') {
611581
// A class declaration name could shadow an import, so add its name to the parent scope
612582
const parentScope = findParentScope(parentStack)

0 commit comments

Comments
 (0)