1
0
Fork 0

Fallback to TypeScript compilation for wasm.ts

This commit is contained in:
Pabloader 2024-07-08 21:46:35 +00:00
parent 576e191631
commit a8bfe73321
3 changed files with 53 additions and 33 deletions

View File

@ -9,7 +9,7 @@ import lightningcss from 'bun-lightningcss';
import { getGames } from './isGame'; import { getGames } from './isGame';
export async function buildHTML(game: string, production = false) { export async function buildHTML(game: string, production = false, portable = false) {
const html = await Bun.file(path.resolve(import.meta.dir, '..', 'assets', 'index.html')).text(); const html = await Bun.file(path.resolve(import.meta.dir, '..', 'assets', 'index.html')).text();
const bundle = await Bun.build({ const bundle = await Bun.build({
outdir: '/tmp', outdir: '/tmp',
@ -23,7 +23,7 @@ export async function buildHTML(game: string, production = false) {
plugins: [ plugins: [
imagePlugin, imagePlugin,
fontPlugin, fontPlugin,
wasmPlugin, wasmPlugin({ production, portable }),
lightningcss(), lightningcss(),
] ]
}); });

View File

@ -15,7 +15,11 @@ Bun.serve({
case '/': case '/':
case 'index.html': case 'index.html':
try { try {
const html = await buildHTML(game); const html = await buildHTML(
game,
url.searchParams.get('production') === 'true', // to debug production builds
url.searchParams.get('portable') === 'true', // to skip AssemblyScript compilation
);
if (html) { if (html) {
return new Response(html, { return new Response(html, {
headers: { headers: {

View File

@ -2,38 +2,54 @@ import { plugin, type BunPlugin } from "bun";
import path from 'path'; import path from 'path';
import asc from 'assemblyscript/asc'; import asc from 'assemblyscript/asc';
const wasmPlugin: BunPlugin = { interface WasmLoaderConfig {
name: "WASM loader", production?: boolean;
async setup(build) { portable?: boolean;
build.onLoad({ filter: /\.wasm\.ts$/ }, async (args) => { }
const wasmPath = path.resolve(import.meta.dir, '..', '..', 'dist', 'tmp.wasm');
const jsPath = wasmPath.replace(/\.wasm$/, '.js');
const { error, stderr } = await asc.main([
args.path,
'--outFile', wasmPath,
'--textFile', wasmPath.replace(/\.wasm$/, '.wat'),
'--optimize', '--bindings', 'esm',
]);
if (error) { const wasmPlugin = ({ production, portable }: WasmLoaderConfig = {}): BunPlugin => {
console.error(stderr.toString(), error.message); const p: BunPlugin = {
throw error; name: "WASM loader",
} else { async setup(build) {
const jsContent = await Bun.file(jsPath).text(); build.onLoad({ filter: /\.wasm\.ts$/ }, async (args) => {
const wasmContent = await Bun.file(wasmPath).arrayBuffer(); if (portable) {
const wasmBuffer = Buffer.from(wasmContent).toString('base64'); const contents = await Bun.file(args.path).text();
const wasmURL = `data:application/wasm;base64,${wasmBuffer}`; return {
contents: `import "assemblyscript/std/portable/index.js";\n${contents}`,
loader: 'tsx',
}
}
const wasmPath = path.resolve(import.meta.dir, '..', '..', 'dist', 'tmp.wasm');
const jsPath = wasmPath.replace(/\.wasm$/, '.js');
const ascArgs = [
args.path,
'--outFile', wasmPath,
'--bindings', 'esm',
];
ascArgs.push(production ? '--optimize' : '--debug');
return { const { error, stderr } = await asc.main(ascArgs);
loader: 'js',
contents: jsContent if (error) {
.replace(/new URL\([^)]*\)/, `new URL(${JSON.stringify(wasmURL)})`), console.error(stderr.toString(), error.message);
}; throw error;
} } else {
}); const jsContent = await Bun.file(jsPath).text();
} const wasmContent = await Bun.file(wasmPath).arrayBuffer();
const wasmBuffer = Buffer.from(wasmContent).toString('base64');
const wasmURL = `data:application/wasm;base64,${wasmBuffer}`;
return {
loader: 'js',
contents: jsContent
.replace(/new URL\([^)]*\)/, `new URL(${JSON.stringify(wasmURL)})`),
};
}
});
}
};
plugin(p);
return p;
}; };
plugin(wasmPlugin);
export default wasmPlugin; export default wasmPlugin;