diff --git a/packages/plugin-rsc/src/transforms/module-export-effect.test.ts b/packages/plugin-rsc/src/transforms/module-export-effect.test.ts index cace6e975..ff644c7f5 100644 --- a/packages/plugin-rsc/src/transforms/module-export-effect.test.ts +++ b/packages/plugin-rsc/src/transforms/module-export-effect.test.ts @@ -93,6 +93,7 @@ export default async function Page() {} ['literal', `export const action = 1`], ['object', `export const action = {}`], ['array', `export const action = []`], + ['uninitialized variable', `export let action`], ])('rejects %s exports', async (_name, input) => { await expect( transform(input, { rejectNonAsyncFunction: true }), diff --git a/packages/plugin-rsc/src/transforms/module-export-effect.ts b/packages/plugin-rsc/src/transforms/module-export-effect.ts index d6d6b633e..39055a99a 100644 --- a/packages/plugin-rsc/src/transforms/module-export-effect.ts +++ b/packages/plugin-rsc/src/transforms/module-export-effect.ts @@ -3,7 +3,7 @@ import type { Identifier } from 'estree' import MagicString from 'magic-string' import type { ESTree } from 'vite' import { scanModuleExports, type ModuleExportMeta } from './module-export-scan' -import { validateNonAsyncFunction } from './utils' +import { rejectNonAsyncFunction, validateNonAsyncFunction } from './utils' // TODO: Metadata, filtering, and returned reference contexts are currently // ported only for transformWrapExport compatibility. Remove them if no @@ -128,8 +128,13 @@ export function transformModuleExportEffect( effects.push(generate({ binding, exportName, meta })) } } - if (validate && declarator.node.init) { - validateNonAsyncFunction(options, declarator.node.init) + if (validate) { + const init = declarator.node.init + if (init) { + validateNonAsyncFunction(options, init) + } else { + rejectNonAsyncFunction(options, declarator.node.start) + } } } if (effects.length > 0) { diff --git a/packages/plugin-rsc/src/transforms/utils.ts b/packages/plugin-rsc/src/transforms/utils.ts index 100d9ce05..3affcbdfc 100644 --- a/packages/plugin-rsc/src/transforms/utils.ts +++ b/packages/plugin-rsc/src/transforms/utils.ts @@ -78,7 +78,6 @@ export function validateNonAsyncFunction( // export default function/class can be unnamed node: Node | ExportDefaultDeclaration['declaration'], ): void { - if (!opts.rejectNonAsyncFunction) return if ( node.type === 'Literal' || node.type === 'ObjectExpression' || @@ -90,8 +89,15 @@ export function validateNonAsyncFunction( node.type === 'ArrowFunctionExpression') && !node.async) ) { - throw Object.assign(new Error(`unsupported non async function`), { - pos: node.start, - }) + rejectNonAsyncFunction(opts, node.start) + } +} + +export function rejectNonAsyncFunction( + opts: { rejectNonAsyncFunction?: boolean }, + pos: number, +): void { + if (opts.rejectNonAsyncFunction) { + throw Object.assign(new Error(`unsupported non async function`), { pos }) } }