Skip to content

Commit 24c866f

Browse files
authored
fix(ssr): fix mistakenly overwriting destructure variables as import bindings (#2417)
fix #2409
1 parent e034ee2 commit 24c866f

File tree

2 files changed

+69
-16
lines changed

2 files changed

+69
-16
lines changed

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

+27
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,30 @@ test('sourcemap source', async () => {
198198
(await ssrTransform(`export const a = 1`, null, 'input.js')).map.sources
199199
).toStrictEqual(['input.js'])
200200
})
201+
202+
test('overwrite bindings', async () => {
203+
expect(
204+
(
205+
await ssrTransform(
206+
`import { inject } from 'vue';` +
207+
`const a = { inject }\n` +
208+
`const b = { test: inject }\n` +
209+
`function c() { const { test: inject } = { test: true }; console.log(inject) }\n` +
210+
`const d = inject \n` +
211+
`function f() { console.log(inject) }\n` +
212+
`function e() { const { inject } = { inject: true } }\n`,
213+
null,
214+
null
215+
)
216+
).code
217+
).toMatchInlineSnapshot(`
218+
"const __vite_ssr_import_0__ = __vite_ssr_import__(\\"vue\\")
219+
const a = { inject: __vite_ssr_import_0__.inject }
220+
const b = { test: __vite_ssr_import_0__.inject }
221+
function c() { const { test: inject } = { test: true }; console.log(inject) }
222+
const d = __vite_ssr_import_0__.inject
223+
function f() { console.log(__vite_ssr_import_0__.inject) }
224+
function e() { const { inject } = { inject: true } }
225+
"
226+
`)
227+
})

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

+42-16
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,23 @@ function walk(
225225
const scope: Record<string, number> = Object.create(null)
226226
const scopeMap = new WeakMap<_Node, Set<string>>()
227227

228+
const setScope = (node: FunctionNode, name: string) => {
229+
let scopeIds = scopeMap.get(node)
230+
if (scopeIds && scopeIds.has(name)) {
231+
return
232+
}
233+
if (name in scope) {
234+
scope[name]++
235+
} else {
236+
scope[name] = 1
237+
}
238+
if (!scopeIds) {
239+
scopeIds = new Set()
240+
scopeMap.set(node, scopeIds)
241+
}
242+
scopeIds.add(name)
243+
}
244+
228245
;(eswalk as any)(root, {
229246
enter(node: Node, parent: Node | null) {
230247
if (node.type === 'ImportDeclaration') {
@@ -261,28 +278,29 @@ function walk(
261278
parent.right === child
262279
)
263280
) {
264-
const { name } = child
265-
let scopeIds = scopeMap.get(node)
266-
if (scopeIds && scopeIds.has(name)) {
267-
return
268-
}
269-
if (name in scope) {
270-
scope[name]++
271-
} else {
272-
scope[name] = 1
273-
}
274-
if (!scopeIds) {
275-
scopeIds = new Set()
276-
scopeMap.set(node, scopeIds)
277-
}
278-
scopeIds.add(name)
281+
setScope(node, child.name)
279282
}
280283
}
281284
})
282285
)
283286
} else if (node.type === 'Property' && parent!.type === 'ObjectPattern') {
284287
// mark property in destructure pattern
285288
;(node as any).inPattern = true
289+
} else if (node.type === 'VariableDeclarator') {
290+
const parentFunction = findParentFunction(parentStack)
291+
if (parentFunction) {
292+
if (node.id.type === 'ObjectPattern') {
293+
node.id.properties.forEach((property) => {
294+
if (property.type === 'RestElement') {
295+
setScope(parentFunction, (property.argument as Identifier).name)
296+
} else {
297+
setScope(parentFunction, (property.value as Identifier).name)
298+
}
299+
})
300+
} else {
301+
setScope(parentFunction, (node.id as Identifier).name)
302+
}
303+
}
286304
}
287305
},
288306

@@ -329,7 +347,7 @@ function isRefIdentifier(id: Identifier, parent: _Node, parentStack: _Node[]) {
329347

330348
// property key
331349
// this also covers object destructure pattern
332-
if (isStaticPropertyKey(id, parent)) {
350+
if (isStaticPropertyKey(id, parent) || (parent as any).inPattern) {
333351
return false
334352
}
335353

@@ -372,6 +390,14 @@ function isFunction(node: _Node): node is FunctionNode {
372390
return /Function(?:Expression|Declaration)$|Method$/.test(node.type)
373391
}
374392

393+
function findParentFunction(parentStack: _Node[]): FunctionNode | undefined {
394+
for (const node of parentStack) {
395+
if (isFunction(node)) {
396+
return node
397+
}
398+
}
399+
}
400+
375401
function isInDestructureAssignment(
376402
parent: _Node,
377403
parentStack: _Node[]

0 commit comments

Comments
 (0)