From 68e90f6a06502192a1b4ca6e9eaf5a94a846361d Mon Sep 17 00:00:00 2001 From: Hampus Date: Tue, 10 Feb 2026 13:46:16 +0100 Subject: [PATCH] fix(app): correctly use generated libfluxcore wasm (#79) --- fluxer_app/src/lib/libfluxcore.worker.ts | 174 ++--------------------- 1 file changed, 13 insertions(+), 161 deletions(-) diff --git a/fluxer_app/src/lib/libfluxcore.worker.ts b/fluxer_app/src/lib/libfluxcore.worker.ts index 89a65fae..9fec0ebb 100644 --- a/fluxer_app/src/lib/libfluxcore.worker.ts +++ b/fluxer_app/src/lib/libfluxcore.worker.ts @@ -17,144 +17,23 @@ * along with Fluxer. If not, see . */ -let cachedWasm: WebAssembly.Instance | null = null; -let wasmMemory: WebAssembly.Memory | null = null; -let wasmExternrefTable: WebAssembly.Table | null = null; -let wasmModule: WebAssembly.Module | null = null; +import initLibfluxcore, * as wasm from '@pkgs/libfluxcore/libfluxcore'; -declare const self: DedicatedWorkerGlobalScope; +let modulePromise: Promise | null = null; -function getArrayU8FromWasm0(ptr: number, len: number): Uint8Array { - ptr = ptr >>> 0; - return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len); -} - -let cachedUint8ArrayMemory0: Uint8Array | null = null; -function getUint8ArrayMemory0(): Uint8Array { - if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) { - cachedUint8ArrayMemory0 = new Uint8Array(wasmMemory!.buffer); +async function loadModule(): Promise { + if (!modulePromise) { + modulePromise = (async () => { + if (typeof initLibfluxcore === 'function') { + await initLibfluxcore(); + } + })(); } - return cachedUint8ArrayMemory0; -} - -function isLikeNone(x: unknown): x is null | undefined { - return x === null || x === undefined; -} - -let WASM_VECTOR_LEN = 0; - -function passArray8ToWasm0(arg: Uint8Array, malloc: (n: number, align: number) => number): number { - const ptr = malloc(arg.length * 1, 1) >>> 0; - getUint8ArrayMemory0().set(arg, ptr / 1); - WASM_VECTOR_LEN = arg.length; - return ptr; -} - -let cachedTextDecoder = new TextDecoder('utf-8', {ignoreBOM: true, fatal: true}); -cachedTextDecoder.decode(); - -const MAX_SAFARI_DECODE_BYTES = 2146435072; -let numBytesDecoded = 0; - -function decodeText(ptr: number, len: number): string { - numBytesDecoded += len; - if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) { - cachedTextDecoder = new TextDecoder('utf-8', {ignoreBOM: true, fatal: true}); - cachedTextDecoder.decode(); - numBytesDecoded = len; - } - return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len)); -} - -function takeObject(idx: number): any { - const ret = wasmExternrefTable!.get(idx); - wasmExternrefTable!.set(idx, undefined); - return ret; -} - -async function loadWasmModule(wasmUrl: string): Promise { - if (cachedWasm) { - return; - } - - const response = await fetch(wasmUrl); - if (!response.ok) { - throw new Error(`Failed to fetch WASM: ${response.statusText}`); - } - - const buffer = await response.arrayBuffer(); - wasmModule = await WebAssembly.compile(buffer); - - const imports = getImports(); - const instance = await WebAssembly.instantiate(wasmModule, imports); - cachedWasm = instance; - - wasmMemory = instance.exports.memory as WebAssembly.Memory; - wasmExternrefTable = instance.exports.__wbindgen_externref_table as WebAssembly.Table; - - cachedUint8ArrayMemory0 = null; - - const exports = instance.exports as any; - exports.__wbindgen_start(); -} - -function getImports(): Record { - const imports: Record = { - wbg: {}, - }; - - imports.wbg.__wbindgen_string_get = (arg0: number, arg1: number) => { - const ret = decodeText(arg0, arg1); - return ret; - }; - - imports.wbg.__wbindgen_is_null = (arg0: number) => (arg0 === 0 ? 1 : 0); - - imports.wbg.__wbindgen_is_undefined = (arg0: number) => (arg0 === 0 ? 1 : 0); - - imports.wbg.__wbindgen_number_get = (_arg0: number, arg1: number) => { - const obj = takeObject(arg1); - const ret = typeof obj === 'number' ? obj : undefined; - return ret; - }; - - imports.wbg.__wbindgen_object_clone_ref = (arg0: number) => { - const obj = takeObject(arg0); - const ret = obj; - return ret; - }; - - imports.wbg.__wbindgen_object_drop_ref = (_arg0: number) => {}; - - imports.wbg.__wbindgen_cb_drop = (arg0: number) => { - const obj = takeObject(arg0).original; - if (obj.cnt-- === 1) { - obj.a = 0; - return 1; - } - return 0; - }; - - imports.wbg.__wbindgen_init_externref_table = () => { - const table = wasmExternrefTable!; - const offset = table.grow(4); - table.set(0, undefined); - table.set(offset + 0, undefined); - table.set(offset + 1, null); - table.set(offset + 2, true); - table.set(offset + 3, false); - }; - - imports.wbg.__wbindgen_throw = (arg0: number, arg1: number) => { - throw new Error(decodeText(arg0, arg1)); - }; - - return imports; + await modulePromise; } export async function ensureLibfluxcoreReady(): Promise { - const wasmUrl = new URL('@pkgs/libfluxcore/libfluxcore_bg.wasm', import.meta.url); - await loadWasmModule(wasmUrl.href); + await loadModule(); } export function cropAndRotateGif( @@ -167,33 +46,6 @@ export function cropAndRotateGif( resizeWidth: number | null, resizeHeight: number | null, ): Uint8Array { - if (!cachedWasm) { - throw new Error('WASM module not loaded. Call ensureLibfluxcoreReady() first.'); - } - - const exports = cachedWasm.exports as any; - - const ptr0 = passArray8ToWasm0(gif, exports.__wbindgen_malloc); - const len0 = WASM_VECTOR_LEN; - - const ret = exports.crop_and_rotate_gif( - ptr0, - len0, - x, - y, - width, - height, - rotation, - isLikeNone(resizeWidth) ? 0x100000001 : (resizeWidth ?? 0) >>> 0, - isLikeNone(resizeHeight) ? 0x100000001 : (resizeHeight ?? 0) >>> 0, - ); - - if (ret[3]) { - throw takeObject(ret[2]); - } - - const v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice(); - exports.__wbindgen_free(ret[0], ret[1] * 1, 1); - - return v2; + const result = wasm.crop_and_rotate_gif(gif, x, y, width, height, rotation, resizeWidth, resizeHeight); + return result instanceof Uint8Array ? result : new Uint8Array(result); }