Skip to content

Commit 17437f8

Browse files
hi-ogawaOpenCode
andcommitted
docs(rsc): explain module export rewrite helpers
Co-authored-by: OpenCode <noreply@opencode.ai>
1 parent f831e47 commit 17437f8

1 file changed

Lines changed: 51 additions & 14 deletions

File tree

packages/plugin-rsc/src/transforms/module-export-wrap.ts

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -149,15 +149,32 @@ export function transformModuleExportWrap(
149149
return `$$module_${references.length}_${kind}_${name}`
150150
}
151151

152+
/**
153+
* Wraps an export whose original local initialization must remain in place,
154+
* such as a class, an arbitrary expression, or an export specifier. The
155+
* generated wrapper is assigned to a separate binding and exported after the
156+
* source declarations, leaving the original local binding unchanged.
157+
*
158+
* For `emitFallback('value', 'renamed', meta)`:
159+
*
160+
* ```js
161+
* // Existing source initialization, left in place
162+
* const value = init()
163+
*
164+
* // Code appended by emitFallback
165+
* const $$module_0_binding_renamed = __WRAP__(value, 'renamed')
166+
* export { $$module_0_binding_renamed as renamed }
167+
* ```
168+
*
169+
* @param implementation Local expression to pass to the generated wrapper.
170+
* @param exportName Public name for the generated export.
171+
* @param meta Static metadata collected from the original export.
172+
*/
152173
function emitFallback(
153174
implementation: string,
154175
exportName: string,
155176
meta: ModuleExportMeta,
156177
): void {
157-
// const value = init()
158-
// ⬇️ (append after source initialization)
159-
// const $$module_0_binding_value = __WRAP__(value, 'value')
160-
// export { $$module_0_binding_value as value }
161178
const binding = createName('binding', exportName)
162179
const context = createContext(implementation, exportName, meta)
163180
fallbackCode.push(
@@ -166,6 +183,36 @@ export function transformModuleExportWrap(
166183
)
167184
}
168185

186+
/**
187+
* Splits a directly exported function into a private implementation and a
188+
* generated wrapper expression. The implementation is moved after the
189+
* directive prologue, while the caller inserts the wrapper at the original
190+
* declaration site. The context includes the source-level function name so
191+
* the generated expression can restore it on the exported callable.
192+
*
193+
* For `hoistFunction(node, 'action', 'action', meta)`:
194+
*
195+
* ```js
196+
* // Before
197+
* export async function action() {}
198+
*
199+
* // Moved into output by hoistFunction
200+
* const $$module_0_implementation_action =
201+
* async function $$module_0_implementation_action() {}
202+
*
203+
* // Returned by hoistFunction
204+
* __WRAP__($$module_0_implementation_action, 'action')
205+
*
206+
* // Final declaration assembled by the caller
207+
* export const action = __WRAP__($$module_0_implementation_action, 'action')
208+
* ```
209+
*
210+
* @param node Directly exported function node to move.
211+
* @param sourceName Local declaration name used for the implementation binding.
212+
* @param exportName Public name for the generated export.
213+
* @param meta Static metadata collected from the original export.
214+
* @returns Generated wrapper expression for the original declaration site.
215+
*/
169216
function hoistFunction(
170217
node: ModuleExportFunction,
171218
sourceName: string,
@@ -174,10 +221,6 @@ export function transformModuleExportWrap(
174221
): string {
175222
validateNonAsyncFunction(options, node)
176223
const implementation = createName('implementation', sourceName)
177-
// export async function action() {}
178-
// ^^^^^^
179-
// ⬇️ (rename before moving)
180-
// const $$module_0_implementation_action = async function $$module_0_implementation_action() {}
181224
const originalPrefix =
182225
node.type === 'FunctionDeclaration' && node.id
183226
? input.slice(node.start, node.id.start) +
@@ -195,12 +238,6 @@ export function transformModuleExportWrap(
195238
`\nconst ${implementation} = ${originalPrefix}`,
196239
)
197240
output.appendLeft(node.end, ';\n')
198-
// 'use server'
199-
// export async function action() {}
200-
// ⬇️ (move after directives and before the wrapper)
201-
// 'use server'
202-
// const $$module_0_implementation_action = async function ...
203-
// export const action = __WRAP__($$module_0_implementation_action, 'action')
204241
output.move(node.start, node.end, hoistPosition)
205242

206243
const context = createContext(

0 commit comments

Comments
 (0)