Skip to content

Commit

Permalink
fix: fix some arbitrary module namespace handling
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red committed Sep 25, 2024
1 parent fcee890 commit c29f263
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 30 deletions.
24 changes: 23 additions & 1 deletion packages/vite/src/node/ssr/__tests__/ssrTransform.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,14 +134,36 @@ test('export * as from', async () => {
`)
})

test('export * as from arbitrary module namespace identifier', async () => {
expect(
await ssrTransformSimpleCode(`export * as "arbitrary string" from 'vue'`),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__("vue");
Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__ }});"
`)
})

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 }});"
Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ return something }});"
`)
})

test('export as from arbitrary module namespace identifier', async () => {
expect(
await ssrTransformSimpleCode(
`export { "arbitrary string2" as "arbitrary string" } from 'vue';`,
),
).toMatchInlineSnapshot(`
"const __vite_ssr_import_0__ = await __vite_ssr_import__("vue", {"importedNames":["arbitrary string2"]});
Object.defineProperty(__vite_ssr_exports__, "arbitrary string", { enumerable: true, configurable: true, get(){ return __vite_ssr_import_0__["arbitrary string2"] }});"
`)
})

Expand Down
66 changes: 37 additions & 29 deletions packages/vite/src/node/ssr/ssrTransform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
Function as FunctionNode,
Identifier,
ImportDeclaration,
Literal,
Pattern,
Property,
VariableDeclaration,
Expand Down Expand Up @@ -130,7 +131,7 @@ async function ssrTransformScript(
function defineExport(position: number, name: string, local = name) {
s.appendLeft(
position,
`\nObject.defineProperty(${ssrModuleExportsKey}, "${name}", ` +
`\nObject.defineProperty(${ssrModuleExportsKey}, ${JSON.stringify(name)}, ` +
`{ enumerable: true, configurable: true, get(){ return ${local} }});`,
)
}
Expand Down Expand Up @@ -163,10 +164,7 @@ async function ssrTransformScript(
importedNames: node.specifiers
.map((s) => {
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
return getIdentifierNameOrLiteralValue(s.imported) as string
else if (s.type === 'ImportDefaultSpecifier') return 'default'
})
.filter(isDefined),
Expand All @@ -182,10 +180,7 @@ async function ssrTransformScript(
} 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)
}]`,
`${importId}[${JSON.stringify(spec.imported.value as string)}]`,
)
}
} else if (spec.type === 'ImportDefaultSpecifier') {
Expand Down Expand Up @@ -226,33 +221,39 @@ async function ssrTransformScript(
node.start,
node.source.value as string,
{
importedNames: node.specifiers.map((s) => s.local.name),
importedNames: node.specifiers.map(
(s) => getIdentifierNameOrLiteralValue(s.local) as string,
),
},
)
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,
exportedAs,
`${importId}.${spec.local.name}`,
)
const exportedAs = getIdentifierNameOrLiteralValue(
spec.exported,
) as string

if (spec.local.type === 'Identifier') {
defineExport(
node.start,
exportedAs,
`${importId}.${spec.local.name}`,
)
} else {
defineExport(
node.start,
exportedAs,
`${importId}[${JSON.stringify(spec.local.value as string)}]`,
)
}
}
} else {
// export { foo, bar }
for (const spec of node.specifiers) {
const local = spec.local.name
// spec.local can be Literal only when it has "from 'something'"
const local = (spec.local as Identifier).name
const binding = idToImportMap.get(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
const exportedAs = getIdentifierNameOrLiteralValue(
spec.exported,
) as string

defineExport(node.end, exportedAs, binding || local)
}
Expand Down Expand Up @@ -292,7 +293,10 @@ async function ssrTransformScript(
s.remove(node.start, node.end)
const importId = defineImport(node.start, node.source.value as string)
if (node.exported) {
defineExport(node.start, node.exported.name, `${importId}`)
const exportedAs = getIdentifierNameOrLiteralValue(
node.exported,
) as string
defineExport(node.start, exportedAs, `${importId}`)
} else {
s.appendLeft(node.start, `${ssrExportAllKey}(${importId});\n`)
}
Expand Down Expand Up @@ -377,6 +381,10 @@ async function ssrTransformScript(
}
}

function getIdentifierNameOrLiteralValue(node: Identifier | Literal) {
return node.type === 'Identifier' ? node.name : node.value
}

interface Visitors {
onIdentifier: (
node: Identifier & {
Expand Down

0 comments on commit c29f263

Please sign in to comment.