second-state/rustwasmc

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

Opened this issue · 0 comments

This is going to be similar to this issue, but I feel like this is a better place for it since it seems like the error is coming from the JS code generation. First, the code:

#[macro_use]
extern crate arrayref;

use wasm_bindgen::{JsValue, throw_str};

use grammers_crypto::aes::{ige_encrypt as _ige_encrypt, ige_decrypt as _ige_decrypt};
use wasm_bindgen::prelude::{wasm_bindgen};

#[wasm_bindgen]
pub fn ige_encrypt(plaintext: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>, JsValue> {
    if plaintext.len() % 16 != 0 {
        throw_str("plaintext must be divisible by 16")
    }

    if key.len() != 32 {
        throw_str("key must contain 32 bits")
    }

    if iv.len() != 32 {
        throw_str("key must contain 32 bits")
    }

    Ok(_ige_encrypt(plaintext, array_ref!(key, 0, 32), array_ref!(iv, 0, 32)))
}

I've omitted the ige_decrypt method for brevity.

When generating a JS file for this code using the command: rustwasmc build --target deno I end up with a mostly correct file. The error seems to be happening the it comes to setting the wasi_snapshot_preview1 key on the imports object. Instead of assigning the key to the existing object, it overwrites the object entirely.

Here are the relevant code snippets:

let imports = {};
imports['__wbindgen_placeholder__'] = {};
let wasm;

// ...

const __wbindgen_throw = function(arg0, arg1) {
    throw new Error(getStringFromWasm0(arg0, arg1));
};
export { __wbindgen_throw };
imports['__wbindgen_placeholder__']['__wbindgen_throw'] = __wbindgen_throw;

import * as path from 'https://deno.land/std/path/mod.ts';
import WASI from 'https://deno.land/std/wasi/snapshot_preview1.ts';
const __dirname = path.dirname(new URL(import.meta.url).pathname);
const wasi = new WASI({
    args: Deno.args,
    env: Deno.env.toObject(),
    preopens: {
        '/': __dirname
    }
});
imports = { wasi_snapshot_preview1: wasi.exports };

const p = path.join(__dirname, 'wasm_crypto_bg.wasm');
const bytes = Deno.readFileSync(p);
const wasmModule = new WebAssembly.Module(bytes);
const wasmInstance = new WebAssembly.Instance(wasmModule, imports);
wasm = wasmInstance.exports;

wasi.memory = wasmInstance.exports.memory;

Hope this is enough info. I'm running the latest version of rustwasmc currently, 0.1.28.