From 0a76652c335e7c0bd8d223186b5533c0e10cac90 Mon Sep 17 00:00:00 2001 From: gtmnayan <50981692+gtm-nayan@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:21:20 +0545 Subject: [PATCH] fix(ssrTransform): handle arbitrary module namespace identifiers (#17446) --- .../node/ssr/__tests__/ssrTransform.spec.ts | 22 ++++++++++ packages/vite/src/node/ssr/ssrTransform.ts | 41 +++++++++++++++---- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts index 9d1e5403c67845..1c268835117deb 100644 --- a/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts +++ b/packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts @@ -27,6 +27,17 @@ test('named import', async () => { `) }) +test('named import: arbitrary module namespace specifier', async () => { + expect( + await ssrTransformSimpleCode( + `import { "some thing" as ref } from 'vue';function foo() { return ref(0) }`, + ), + ).toMatchInlineSnapshot(` + "const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["some thing"]}); + function foo() { return __vite_ssr_import_0__["some thing"](0) }" + `) +}) + test('namespace import', async () => { expect( await ssrTransformSimpleCode( @@ -120,6 +131,17 @@ test('export * as from', async () => { `) }) +test('export as arbitrary module namespace identifier', async () => { + expect( + await ssrTransformSimpleCode( + `const something = "Something";export { something as "arbitrary string" };`, + ), + ).toMatchInlineSnapshot(` + "const something = "Something"; + Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ return something }});" + `) +}) + test('export default', async () => { expect( await ssrTransformSimpleCode(`export default {}`), diff --git a/packages/vite/src/node/ssr/ssrTransform.ts b/packages/vite/src/node/ssr/ssrTransform.ts index 61849d0e3ca4f2..bd99493c1b86a3 100644 --- a/packages/vite/src/node/ssr/ssrTransform.ts +++ b/packages/vite/src/node/ssr/ssrTransform.ts @@ -139,7 +139,11 @@ async function ssrTransformScript( const importId = defineImport(hoistIndex, node.source.value as string, { importedNames: node.specifiers .map((s) => { - if (s.type === 'ImportSpecifier') return s.imported.name + if (s.type === 'ImportSpecifier') + return s.imported.type === 'Identifier' + ? s.imported.name + : // @ts-expect-error TODO: Estree types don't consider arbitrary module namespace specifiers yet + s.imported.value else if (s.type === 'ImportDefaultSpecifier') return 'default' }) .filter(isDefined), @@ -147,10 +151,20 @@ async function ssrTransformScript( s.remove(node.start, node.end) for (const spec of node.specifiers) { if (spec.type === 'ImportSpecifier') { - idToImportMap.set( - spec.local.name, - `${importId}.${spec.imported.name}`, - ) + if (spec.imported.type === 'Identifier') { + idToImportMap.set( + spec.local.name, + `${importId}.${spec.imported.name}`, + ) + } else { + idToImportMap.set( + spec.local.name, + `${importId}[${ + // @ts-expect-error TODO: Estree types don't consider arbitrary module namespace specifiers yet + JSON.stringify(spec.imported.value) + }]`, + ) + } } else if (spec.type === 'ImportDefaultSpecifier') { idToImportMap.set(spec.local.name, `${importId}.default`) } else { @@ -194,9 +208,15 @@ async function ssrTransformScript( }, ) for (const spec of node.specifiers) { + const exportedAs = + spec.exported.type === 'Identifier' + ? spec.exported.name + : // @ts-expect-error TODO: Estree types don't consider arbitrary module namespace specifiers yet + spec.exported.value + defineExport( node.start, - spec.exported.name, + exportedAs, `${importId}.${spec.local.name}`, ) } @@ -205,7 +225,14 @@ async function ssrTransformScript( for (const spec of node.specifiers) { const local = spec.local.name const binding = idToImportMap.get(local) - defineExport(node.end, spec.exported.name, binding || local) + + const exportedAs = + spec.exported.type === 'Identifier' + ? spec.exported.name + : // @ts-expect-error TODO: Estree types don't consider arbitrary module namespace specifiers yet + spec.exported.value + + defineExport(node.end, exportedAs, binding || local) } } }