From 02db9479acfa022503a6e668d347360d916cc298 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Wed, 1 May 2024 16:30:22 +0800 Subject: [PATCH] fix(ssr): handle function expression name scoping (#16563) --- .../node/ssr/__tests__/ssrTransform.spec.ts | 22 +++++++++++++++++++ packages/vite/src/node/ssr/ssrTransform.ts | 5 +++++ 2 files changed, 27 insertions(+) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index 5c99e5cab3ecdb..f2f1428a58311a 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -249,6 +249,28 @@ test('do not rewrite when function declaration is in scope', async () => { expect(result?.deps).toEqual(['vue']) }) +// #16452 +test('do not rewrite when function expression is in scope', async () => { + const result = await ssrTransformSimple( + `import {fn} from './vue';var a = function() { return function fn() { console.log(fn) } }`, + ) + expect(result?.code).toMatchInlineSnapshot(` + "const __vite_ssr_import_0__ = await __vite_ssr_import__("./vue", {"importedNames":["fn"]}); + var a = function() { return function fn() { console.log(fn) } }" + `) +}) + +// #16452 +test('do not rewrite when function expression is in global scope', async () => { + const result = await ssrTransformSimple( + `import {fn} from './vue';foo(function fn(a = fn) { console.log(fn) })`, + ) + expect(result?.code).toMatchInlineSnapshot(` + "const __vite_ssr_import_0__ = await __vite_ssr_import__("./vue", {"importedNames":["fn"]}); + foo(function fn(a = fn) { console.log(fn) })" + `) +}) + test('do not rewrite catch clause', async () => { const result = await ssrTransformSimple( `import {error} from './dependency';try {} catch(error) {}`, diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index c3800a48a8d138..ead6b905e80f13 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -442,6 +442,11 @@ function walk( setScope(parentScope, node.id!.name) } } + // If it is a function expression, its name (if exist) could also be + // shadowing an import. So add its own name to the scope + if (node.type === 'FunctionExpression' && node.id) { + setScope(node, node.id.name) + } // walk function expressions and add its arguments to known identifiers // so that we don't prefix them node.params.forEach((p) => {