diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index a5ca20c9be3d09..33d5071a054a99 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -787,3 +787,27 @@ export class Test { Object.defineProperty(__vite_ssr_exports__, \\"Test\\", { enumerable: true, configurable: true, get(){ return Test }});;" `) }) + +// #10386 +test('track var scope by function', async () => { + expect( + await ssrTransformSimpleCode(` +import { foo, bar } from 'foobar' +function test() { + if (true) { + var foo = () => { var why = 'would' }, bar = 'someone' + } + return [foo, bar] +}`) + ).toMatchInlineSnapshot(` + " + const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\"); + + function test() { + if (true) { + var foo = () => { var why = 'would' }, bar = 'someone' + } + return [foo, bar] + }" + `) +}) diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index fe24dddac2e79a..be25b367970472 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -5,6 +5,7 @@ import type { Identifier, Pattern, Property, + VariableDeclaration, Node as _Node } from 'estree' import { extract_names as extractNames } from 'periscopic' @@ -319,6 +320,7 @@ function walk( { onIdentifier, onImportMeta, onDynamicImport }: Visitors ) { const parentStack: Node[] = [] + const varKindStack: VariableDeclaration['kind'][] = [] const scopeMap = new WeakMap<_Node, Set>() const identifiers: [id: any, stack: Node[]][] = [] @@ -378,6 +380,11 @@ function walk( parentStack.unshift(parent) } + // track variable declaration kind stack used by VariableDeclarator + if (node.type === 'VariableDeclaration') { + varKindStack.unshift(node.kind) + } + if (node.type === 'MetaProperty' && node.meta.name === 'import') { onImportMeta(node) } else if (node.type === 'ImportExpression') { @@ -437,7 +444,10 @@ function walk( // mark property in destructuring pattern setIsNodeInPattern(node) } else if (node.type === 'VariableDeclarator') { - const parentFunction = findParentScope(parentStack) + const parentFunction = findParentScope( + parentStack, + varKindStack[0] === 'var' + ) if (parentFunction) { handlePattern(node.id, parentFunction) } @@ -452,6 +462,10 @@ function walk( ) { parentStack.shift() } + + if (node.type === 'VariableDeclaration') { + varKindStack.shift() + } } }) @@ -541,8 +555,12 @@ function isFunction(node: _Node): node is FunctionNode { const scopeNodeTypeRE = /(?:Function|Class)(?:Expression|Declaration)$|Method$|^IfStatement$/ -function findParentScope(parentStack: _Node[]): _Node | undefined { - return parentStack.find((i) => scopeNodeTypeRE.test(i.type)) +function findParentScope( + parentStack: _Node[], + isVar = false +): _Node | undefined { + const regex = isVar ? functionNodeTypeRE : scopeNodeTypeRE + return parentStack.find((i) => regex.test(i.type)) } function isInDestructuringAssignment(