wasm-bindgen icon indicating copy to clipboard operation
wasm-bindgen copied to clipboard

JS glue: Please provide a way to initialize with an already loaded `WebAssembly.Module`

Open johnspurlock opened this issue 3 years ago • 3 comments

Motivation

Cloudflare Workers has a wacky way of importing wasm modules.

import module from "./hello.wasm";

...is the only allowed way to bring in wasm (in module-based workers). module is then a WebAssembly.Module, not its exports like the upcoming standard proposal.

Currently this means any wasm-bindgen generated JS cannot be initialized properly out of the box. They need to be manually edited with something like a setModule function, which is then picked up and used in instantiateModule.

Once this is done, the wasm lib usually works fine on Cloudflare (modulo some other intentionally missing classes that need to be stubbed like FinalizationRegistry)

Proposed Solution

It would be great if a future version of the JS glue code could accept an WebAssembly.Module already in hand, for environments like this.

Alternatives

Tweaking wasm-bindgen generated JS by hand

Thanks! - John

johnspurlock avatar Jun 30 '22 17:06 johnspurlock

Cloudflare Workers has a wacky way of importing wasm modules.

I completely agree that it would be nicer if this just worked out the box, but it sounds like this is more of an issue with Cloudflare rather than wasm-bindgen, right?

allsey87 avatar Jul 01 '22 14:07 allsey87

It's a constrained and security-focused runtime, so I suppose it's reasonable for them to prevent fetching wasm and instantiating modules on the fly. Instead, they are essentially uploaded (and checked) at deploy time.

They are, however, provided at runtime as a web-standard WebAssembly.Module, and it would be great if the bindgen script supported using it (in instantiateModule) instead of assuming fetch

johnspurlock avatar Jul 01 '22 14:07 johnspurlock

The glue depends on the target. Which target do you use? With --target web, init with WebAssembly.Module does work fine. If you know how to tweak the output file, just tweak the template code in this repo instead and create a PR, like #3016.

lukaslihotzki avatar Aug 03 '22 15:08 lukaslihotzki

Hi @johnspurlock, I believe I have a fix for you in https://github.com/rustwasm/wasm-bindgen/pull/3510.

jkomyno avatar Jul 06 '23 19:07 jkomyno

Thanks! As long as I can hand in my WebAssembly.Module to init, that'll be great

johnspurlock avatar Jul 06 '23 20:07 johnspurlock

@johnspurlock With my PR, you'd only need to:

  • run wasm-bindgen --target bundler --workerd
  • import your Wasm bindings in a Cloudflare Worker, like so:
    import { yourFunction } from './wasm/your_crate.js'
    
    // call yourFunction()
    

jkomyno avatar Jul 06 '23 22:07 jkomyno

As pointed out before in https://github.com/rustwasm/wasm-bindgen/issues/2972#issuecomment-1204150245, the web target already supports importing a module without fetching: https://github.com/rustwasm/wasm-bindgen/blob/e13d8985a24d841a93d35e3e4374ec26f7456e0d/crates/cli-support/src/js/mod.rs#L871-L873

I've been extensively using Cloudflare Workers lately with the Web target, this has worked well for me:

#[wasm_bindgen]
pub fn fetch() -> Result<Response, JsValue> {
    Response::new_with_opt_str(Some("Hello, World!"))
}
import wasm from './test_bg.wasm'
import init, * as exports from './test.js';

await init(wasm);

export default exports;

So I believe this has already been solved by #1384. Please leave a comment if I'm wrong about this!

daxpedda avatar Jul 07 '23 10:07 daxpedda