WebAssembly
JSplitter exposes the standard WebAssembly global in both panels and Workers. WebAssembly modules built from C, C++, Rust or other supported languages can run directly in SpiderMonkey without additional native support from JSplitter.
Loading a module
The simplest approach is to read a local .wasm file as bytes with utils.ReadBinaryFile, then create a module and an instance:
const bytes = utils.ReadBinaryFile('algorithm.wasm');
if (!bytes) throw new Error('Cannot read WASM module');
const module = new WebAssembly.Module(bytes);
const instance = new WebAssembly.Instance(module);
// Call instance.exports.someFunction(...)
For CPU-intensive tasks, consider running WebAssembly in a Worker to keep the panel responsive.
Ready-to-run example: album-art filters
The samples/wasm folder contains a practical example of Sobel edge detection, implemented in C and compiled to a standalone WASM module. It loads the playing or focused track's cover using utils.GetAlbumArtV2. When no artwork is available, it displays a generated test image instead. GDI shows the original and filtered artwork side by side.
To run: select Script → File in a JSplitter panel and choose samples/wasm/WebAssembly Image Filters.js. Do not move this file separately from its Worker or WASM dependencies. The script is ready to run from the distributed samples directory; no build step or additional runtime is necessary. A panel of roughly 650 × 350 pixels works well.
- Left click: switch between Pencil, Neon and Ink modes.
- Mouse wheel: adjust edge-detection threshold.
- Right click: refresh the selected or playing track's cover.
How the example works
- The panel obtains an image and extracts RGBA pixels using GdiBitmap.GetPixelData, then transfers their buffer to a file-backed Worker via Worker#postMessage.
- The Worker reads album_art_filters.wasm with utils.ReadBinaryFile, then constructs its WebAssembly.Module and WebAssembly.Instance once.
- The Worker copies image pixels into the module's exported WebAssembly.Memory. The native filter function reads that region and writes processed RGBA pixels into another region.
- The output is copied out of WASM memory and sent back to the panel, which creates an image via gdi.CreateImageFromPixelData.
- Changing the mode or threshold reuses the existing instance and source pixels in the Worker. Only small parameters need to be sent again.
Memory and data exchange
Compiled code uses offsets into linear WebAssembly.Memory, not direct pointers to arbitrary JavaScript objects. This example obtains the beginning of usable memory from the exported __heap_base global and reserves two aligned RGBA buffers. It grows the memory when required and recreates typed-array views after growth. To transfer the result back, it first copies the output into a separate JavaScript Uint8Array, leaving WASM memory owned by the Worker.
Included files
- WebAssembly Image Filters.js — GDI panel and controls.
- WebAssembly Image Filters.worker.js — Worker and WASM integration.
- album_art_filters.wasm — ready-to-run standalone module.
- source/album_art_filters.c — original C implementation.
- README.md — optional Clang build command.
Limitations
WebAssembly is not automatically a browser or operating-system runtime. Modules built for WASI, Emscripten, Node.js, the DOM, network access, or multi-threading may require additional imports, JavaScript support, or APIs that JSplitter does not provide. WebAssembly also does not guarantee a performance improvement over JavaScript or native code. The timer displayed by this example includes the WASM function call and copying of its output buffer, not full end-to-end rendering or image loading.
The example limits image dimensions to 384 pixels per side to bound memory and CPU cost, including on 32-bit foobar2000. Only use WASM modules whose behavior and resource requirements you trust.
Building the WASM module (optional)
The prebuilt album_art_filters.wasm is included and runs without a build step. To rebuild it after editing source/album_art_filters.c, install Clang with WebAssembly (wasm32) support and wasm-ld. Run the following from component/samples/wasm:
clang --target=wasm32-unknown-unknown -O3 -nostdlib \
-Wl,--no-entry -Wl,--export=filter -Wl,--export-memory \
-Wl,--export=__heap_base -Wl,--initial-memory=131072 \
-o album_art_filters.wasm source/album_art_filters.c
On Windows, enter the command on a single line, removing the backslashes used for line continuation. The command writes album_art_filters.wasm next to the Worker script. The -nostdlib and --no-entry options avoid a C runtime entry point; the linker exports the filter function, linear memory and __heap_base needed by the Worker. This is a build-time step outside JSplitter. The panel and Worker simply load the already-built module.