WASM JS-Error 'module is not an object or function'

I have built a mod-player in rust as a library, which runs fine with the portaudio crate. I am now trying to get this player to work with wasm. However as soon as I instanciate the player, I get a JS-Error:

Uncaught (in promise) TypeError: WebAssembly Instantiation: Import #0 module="env" error: module is not an object or function

This is how I compile the project:

cargo +nightly build --target wasm32-unknown-unknown --release --target-dir site

This is the rust method (I removed all other methods to simplify the situation):

#[no_mangle]
pub fn set_sample_rate(sf: f32) -> *mut rb::rustboy::player::Player {
    Box::into_raw(Box::new(rb::rustboy::player::Player::new(sf as f32)))
}

This is the script part:

<script>
    fetch("./wasm32-unknown-unknown/release/rustboy_web.wasm")
        .then(response => response.arrayBuffer())
        .then(bytes => WebAssembly.instantiate(bytes, {}))
        .then(m => {
            console.log(m); // throws the error
        });
</script>

Is it possible that I am using something in my player code, which does not compile to WASM? It is actually quite simple code without any serious rust magic. Any help is appreciated.

{} is where imports go. Currently only everything goes in env module. Rust lazily adds a short list of imports when required.
Partially complete compact object would be;
{ env: { Math_asos: Math.acos, Math_asin: Math.asin } }

https://github.com/rust-lang/rust/blob/560a5da9f1cc7f67d2fc372925aef18c96c82629/src/libstd/sys/wasm/cmath.rs#L77-L119

1 Like

Thanks!

I hope you can help me with the immediate next issue:

#[no_mangle]
pub extern "C" fn set_format(ptr: *mut JsBytes) -> u32 {
    let vector = unsafe {
        let boxed: Box<JsBytes> = Box::from_raw(ptr);
        Vec::from_raw_parts(boxed.ptr as *mut u8, boxed.len as usize, boxed.cap as usize)
    };
    let format = rb::rustboy::format::Format::from(vector); // throws the error
    format.samples.len() as u32
}

calling this method where the format is parsed leads to:

wasm-0029291e-1770:2 Uncaught (in promise) RuntimeError: unreachable
at __rust_start_panic (wasm-function[1770]:1)
at rust_panic.llvm.16567003484150349135 (wasm-function[862]:38)
at _ZN3std9panicking20rust_panic_with_hook17hbc2047e403c353d2E (wasm-function[859]:500)
at _ZN3std9panicking18continue_panic_fmt17h5a2621d3417d60fdE (wasm-function[856]:155)
at rust_begin_unwind (wasm-function[855]:3)
at _ZN4core9panicking9panic_fmt17h836ab8dd5ea230eeE (wasm-function[2510]:80)
at _ZN4core9panicking5panic17h7461b0dd1cdfc386E (wasm-function[2509]:109)
at _ZN7rustboy7rustboy6format6Format4from17h795cccc165914577E (wasm-function[92]:1222)
at set_format (wasm-function[23]:86)
at readBinary.then.bytes (http://localhost:63343/site/index.html?_ijt=p9cvhjcbm69psj0dtetb7j1u58:37:41)

while this works (without format):

#[no_mangle]
pub extern "C" fn set_format(ptr: *mut JsBytes) -> u32 {
 let vector = unsafe {
  let boxed: Box<JsBytes> = Box::from_raw(ptr);
  Vec::from_raw_parts(boxed.ptr as *mut u8, boxed.len as usize, boxed.cap as usize)
 };
 vector.len() as u32 // returns the correct format file size
}

Unreachable seems to be an error that occurs when there are instructions that cannot be resolved in WASM.

In my case:

pub fn from(data: Vec<u8>) {
    let title = read_string(&data, 0, 20);
    let sequence_length: usize = data[0x3b6] as usize;
    let sequence = Vec::from(&data[0x3B8..0x3B8 + sequence_length]);
    let num_patterns = (sequence.iter().max().unwrap() + 1) as usize; // unreachable
    ...

Is there a safe way to resolve the line?

The naive way works, but I would love to understand what was wrong with the initial code.

    let sequence = Vec::from(&data[0x3B8..0x3B8 + sequence_length]);
    let mut num_patterns = 0u8;//(sequence.iter().max().unwrap() + 1) as usize;
    for x in sequence.iter() {
        if num_patterns < *x {
            num_patterns = *x;
        }
    }
    num_patterns += 1;