Environment
unplugin@3.0.0 + bun@1.3.13
Reproduction
import { createBunPlugin } from 'unplugin'
await Bun.write(
'./entry.ts',
"import Hello from 'virtual:component'; console.log(<Hello />);\n",
)
const plugin = createBunPlugin(() => ({
name: 'jsx-virtual',
resolveId(id) {
return id === 'virtual:component' ? id : null
},
load(id) {
if (id === 'virtual:component') {
return 'export default () => <h1>hi</h1>'
}
return null
},
}))()
await Bun.build({
entrypoints: ['./entry.ts'],
plugins: [plugin],
})
Describe the bug
In the Bun adapter, the Loader for a load hook's returned contents is inferred from path.extname(id) via guessLoader (src/bun/utils.ts). The result is passed as the loader field on Bun's onLoad return.
This is fine for 'file' namespace loads where the id is a real file path, but for virtual modules the id has no meaningful extension (or carries a query suffix that confuses extname). Bun then falls back to js, which fails when the plugin's returned contents are JSX/TSX/CSS/etc.
Plugins have no way to tell unplugin "this content is tsx" — the existing LoadResult type only carries code and map. esbuild's own onLoad accepts { contents, loader }; unplugin's Bun adapter should let plugins pass the same hint.
Additional context
No response
Logs
$ bun run 02-loader.ts
1 | export default () => <h1>hi</h1>
^
error: Unexpected <
at virtual:component:1:22
Environment
unplugin@3.0.0 + bun@1.3.13
Reproduction
Describe the bug
In the Bun adapter, the
Loaderfor aloadhook's returnedcontentsis inferred frompath.extname(id)viaguessLoader(src/bun/utils.ts). The result is passed as theloaderfield on Bun'sonLoadreturn.This is fine for
'file'namespace loads where the id is a real file path, but for virtual modules the id has no meaningful extension (or carries a query suffix that confuses extname). Bun then falls back tojs, which fails when the plugin's returnedcontentsare JSX/TSX/CSS/etc.Plugins have no way to tell unplugin "this content is
tsx" — the existingLoadResulttype only carriescodeandmap. esbuild's ownonLoadaccepts{ contents, loader }; unplugin's Bun adapter should let plugins pass the same hint.Additional context
No response
Logs