Search code examples
webassemblyassemblyscript

Transfer byte array (Uint8Array) between WebAssembly and JavaScript


I have a u8[] array in WebAssembly code, how can I read it in regular JS? Calls to it just return me a i32.

// Load module WebAssembly.Instance
const instance = await getInstance("./build/embed.wasm");

// Try to get the array of bytes from the module
const embeddedFileBytes = Uint8Array.from(instance.fileBytes);

// write the file to disc
await writeFile("./output.text", embeddedFileBytes);

// check the hash is the same as the original file that was embedded
expect(sha1("./output.text")).toEqual(sha1("./input.text"))

The webassembly module has an export:

export const fileBytes: u8[] = [83,65,77,80,76,69,10];

Solution

  • WebAssembly is a low level virtual machine that only supports numeric types. More complex types, such as as strings, structs and arrays, are encoded within the WebAssembly's linear memory - which is a contiguous block of memory that both WebAssembly and JavaScript can read and write to.

    The value returned by fileBytes isn't the array itself, it is instead a pointer to the location of the array in linear memory. In order to obtain the data from the array, you'll need to read it from linear memory - in much the same way as you would read a string, as described in the following question:

    How can I return a JavaScript string from a WebAssembly function

    If you don't want to write this 'glue' code yourself, I'd recommend looking into wasm-bindgen