From 6ce167cb20770fd6760325a614d84290561c2cee Mon Sep 17 00:00:00 2001 From: bluwy Date: Sun, 9 Oct 2022 21:32:13 +0800 Subject: [PATCH 1/2] fix(ssr): track var as function scope --- .../node/ssr/__tests__/ssrTransform.spec.ts | 24 +++++++++++++++++++ packages/vite/src/node/ssr/ssrTransform.ts | 21 +++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index a5ca20c9be3d09..c3be5ff10489f6 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 } from 'foobar' +function test() { + if (true) { + var foo = 'shadow' + } + return foo +}`) + ).toMatchInlineSnapshot(` + " + const __vite_ssr_import_0__ = await __vite_ssr_import__(\\"foobar\\"); + + function test() { + if (true) { + var foo = 'shadow' + } + return foo + }" + `) +}) diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index 12c3bb354b6c9e..bedae5c196f359 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' @@ -318,6 +319,7 @@ function walk( const parentStack: Node[] = [] const scopeMap = new WeakMap<_Node, Set>() const identifiers: [id: any, stack: Node[]][] = [] + let variableDeclarationKind: VariableDeclaration['kind'] | undefined const setScope = (node: _Node, name: string) => { let scopeIds = scopeMap.get(node) @@ -434,10 +436,15 @@ function walk( // mark property in destructuring pattern setIsNodeInPattern(node) } else if (node.type === 'VariableDeclarator') { - const parentFunction = findParentScope(parentStack) + const parentFunction = findParentScope( + parentStack, + variableDeclarationKind === 'var' + ) if (parentFunction) { handlePattern(node.id, parentFunction) } + } else if (node.type === 'VariableDeclaration') { + variableDeclarationKind = node.kind } }, @@ -449,6 +456,10 @@ function walk( ) { parentStack.shift() } + + if (node.type === 'VariableDeclaration') { + variableDeclarationKind = undefined + } } }) @@ -538,8 +549,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( From 7dbf1a03dc609cda5ceca8d4fecc31aa2f7bb1c1 Mon Sep 17 00:00:00 2001 From: bluwy Date: Sun, 9 Oct 2022 21:54:36 +0800 Subject: [PATCH 2/2] fix(ssr): handle edge case --- .../src/node/ssr/__tests__/ssrTransform.spec.ts | 10 +++++----- packages/vite/src/node/ssr/ssrTransform.ts | 13 ++++++++----- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index c3be5ff10489f6..33d5071a054a99 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -792,12 +792,12 @@ export class Test { test('track var scope by function', async () => { expect( await ssrTransformSimpleCode(` -import { foo } from 'foobar' +import { foo, bar } from 'foobar' function test() { if (true) { - var foo = 'shadow' + var foo = () => { var why = 'would' }, bar = 'someone' } - return foo + return [foo, bar] }`) ).toMatchInlineSnapshot(` " @@ -805,9 +805,9 @@ function test() { function test() { if (true) { - var foo = 'shadow' + var foo = () => { var why = 'would' }, bar = 'someone' } - return foo + return [foo, bar] }" `) }) diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index bedae5c196f359..eefdf29f70d7a1 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -317,9 +317,9 @@ 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[]][] = [] - let variableDeclarationKind: VariableDeclaration['kind'] | undefined const setScope = (node: _Node, name: string) => { let scopeIds = scopeMap.get(node) @@ -377,6 +377,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') { @@ -438,13 +443,11 @@ function walk( } else if (node.type === 'VariableDeclarator') { const parentFunction = findParentScope( parentStack, - variableDeclarationKind === 'var' + varKindStack[0] === 'var' ) if (parentFunction) { handlePattern(node.id, parentFunction) } - } else if (node.type === 'VariableDeclaration') { - variableDeclarationKind = node.kind } }, @@ -458,7 +461,7 @@ function walk( } if (node.type === 'VariableDeclaration') { - variableDeclarationKind = undefined + varKindStack.shift() } } })