diff --git a/package.json b/package.json index 0982dc3b..b356eaaa 100644 --- a/package.json +++ b/package.json @@ -92,6 +92,7 @@ "verovio": "^6.0.1", "vexflow": "^5.0.0", "vite-plugin-static-copy": "^3.1.6", + "wabt": "^1.0.39", "wavefile": "^11.0.0", "woff2-encoder": "^2.0.0", "yaml": "^2.8.2" diff --git a/src/handlers/index.ts b/src/handlers/index.ts index f49b4f5d..d507eecd 100644 --- a/src/handlers/index.ts +++ b/src/handlers/index.ts @@ -66,6 +66,7 @@ import mclangHandler from "./minecraftLangfileHandler.ts"; import celariaMapHandler from "./celariaMap.ts"; import cybergrindHandler from "./cybergrindHandler.ts"; import textToSourceHandler from "./textToSource.ts"; +import wabtHandler from "./wabtHandler.ts"; import xcursorHandler from "./xcursor.ts"; const handlers: FormatHandler[] = []; @@ -141,6 +142,7 @@ try { handlers.push(new mclangHandler()) } catch (_) { }; try { handlers.push(new celariaMapHandler()) } catch (_) { }; try { handlers.push(new cybergrindHandler()) } catch (_) { }; try { handlers.push(new textToSourceHandler()) } catch (_) { }; +try { handlers.push(new wabtHandler()) } catch (_) { }; try { handlers.push(new xcursorHandler()) } catch (_) { }; export default handlers; diff --git a/src/handlers/wabtHandler.ts b/src/handlers/wabtHandler.ts new file mode 100644 index 00000000..bedc20c3 --- /dev/null +++ b/src/handlers/wabtHandler.ts @@ -0,0 +1,89 @@ +import type { FileData, FileFormat, FormatHandler } from "../FormatHandler.ts"; +import { Category } from "src/CommonFormats.ts"; +import wabt from "wabt"; + +const wabtModule = await wabt(); + +function wasm2wat(bytes: Uint8Array): Uint8Array { + const wasmModule = wabtModule.readWasm(bytes, {}); + const str = wasmModule.toText({}); + const encoder = new TextEncoder(); + return encoder.encode(str); +} + +function wat2wasm(filename: string, bytes: Uint8Array): Uint8Array { + const wasmModule = wabtModule.parseWat(filename, bytes); + const outBytes = wasmModule.toBinary({}); + return outBytes.buffer; +} + +export default class wabtHandler implements FormatHandler { + public name: string = "wabt"; + public supportedFormats?: FileFormat[]; + public ready: boolean = false; + + async init() { + this.supportedFormats = [ + { + name: "WebAssembly Binary (Wasm)", + format: "wasm", + extension: "wasm", + mime: "application/wasm", + from: true, + to: true, + internal: "wasm", + category: Category.CODE, + lossless: true, + }, + { + name: "WebAssembly Text Format (WAT)", + format: "wat", + extension: "wat", + // https://github.com/WebAssembly/spec/issues/1347 + mime: "text/plain", + from: true, + to: true, + internal: "wat", + category: Category.CODE, + lossless: true, + }, + ]; + this.ready = true; + } + + async doConvert( + inputFiles: FileData[], + inputFormat: FileFormat, + outputFormat: FileFormat, + ): Promise { + const outputFiles: FileData[] = []; + + if (inputFormat.internal == "wasm" && outputFormat.internal == "wat") { + for (const file of inputFiles) { + outputFiles.push({ + name: + file.name.split(".").slice(0, -1).join(".") + + `.${outputFormat.extension}`, + bytes: wasm2wat(file.bytes), + }); + } + return outputFiles; + } + + if (inputFormat.internal == "wat" && outputFormat.internal == "wasm") { + for (const file of inputFiles) { + outputFiles.push({ + name: + file.name.split(".").slice(0, -1).join(".") + + `.${outputFormat.extension}`, + bytes: wat2wasm(file.name, file.bytes), + }); + } + return outputFiles; + } + + throw new Error( + `wabtHandler does not support route: ${inputFormat.internal} -> ${outputFormat.internal}`, + ); + } +}