Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more JS initialization options #9

Closed
TimHambourger opened this issue Jan 28, 2018 · 8 comments
Closed

Add more JS initialization options #9

TimHambourger opened this issue Jan 28, 2018 · 8 comments

Comments

@TimHambourger
Copy link

Currently, the CLI-generated TS bindings export a single entry point, instantiate. This internally calls WebAssembly.instantiate and then processes the returned WebAssembly.ResultObject like

function xform(obj: WebAssembly.ResultObject): Exports {
    let { module, instance } = obj;
    // etc.
}

This is a great general starting point, but it has a couple limitations:

  1. You can't pass a pre-compiled WebAssembly.Module to instantiate, since the overload of WebAssembly.instantiate that takes a WebAssembly.Module doesn't return a WebAssembly.ResultObject but instead just a WebAssembly.Instance. So the destructuring above will set both module and instance to undefined.
  2. You can't use the newer WebAssembly.instantiateStreaming API.

Would you support adding a lower-level JS API for these use cases? I'm imagining a pair of functions something like getImports(_imports : Imports) and initWithInstance(instance : WebAssembly.Instance). It'd be up to consuming code to call WebAssembly.instantiate(Streaming), like

import { MyStruct, getImports, initWithInstance } from './cli-generated-bindings.ts';

WebAssembly.instantiateStreaming(fetch('my-wasm.wasm'), getImports({}))
    .then(({ instance }) => initiWithInstance(instance))
    .then(wasm => {
        const myStruct = MyStruct.new();
        wasm.my_rust_fn(myStruct);
        // etc...
    });

This would also support things like fetching and compiling the WASM once via WebAssembly.compile or WebAssembly.compileStreaming and then passing the compiled WebAssembly.Module to multiple worker threads, each of which constructs its own WebAssembly.Instance using the cli-generated bindings.

@alexcrichton
Copy link
Contributor

I'd definitely be on board with this! I like the idea of "given the set of nice imports give me a set of low-level imports" as well as the reverse for the exports. Would you be interested in trying your hand at adding these?

@TimHambourger
Copy link
Author

Great, thanks for the quick response! Yes, I'd be happy to give it a try. It looks like the key file is crates/wasm-bindgen-cli-support/src/ts.rs. Any parallel spots I should look for?

@alexcrichton
Copy link
Contributor

Nah yeah that's it! The file isn't exactly the cleanest of files, but you can see the template down at the bottom

@alexcrichton
Copy link
Contributor

@TimHambourger ah so actually, you may wish to hold off! I was having some discussion today with others and actually I think the current approach to the wasm module isn't quite right. I think we'll want to generate wasm/js files differently to better respect ES6 module integration with wasm.

I'll try to update this repo soon!

@alexcrichton
Copy link
Contributor

As a general overview though what I'd hope to do is to actually generate a JS file file that starts with something like:

import * as wasm from './low-level.wasm';

in the sense that the instantiation of the wasm module would largely be up to the bundler rather than this library.

@alexcrichton
Copy link
Contributor

Ok! I've rewritten the bindgen tool at the es6-modules branch -- https://github.com/alexcrichton/wasm-bindgen/tree/es6-modules, with some notable info in the commit message.

@TimHambourger mind giving that a spin and see if it works for you?

@alexcrichton
Copy link
Contributor

Ah ok I went ahead and merged to master so this should be fixed now!

@TimHambourger
Copy link
Author

@alexcrichton You move fast! Thanks for the updates and sorry to take a couple days to get back.

I definitely appreciate the desire to move instantiation out of this library. I've seen other tools that take a wasm-as-module approach, e.g. wasm-loader for webpack. I like the concept - treat wasm like just another code asset. It seems like the trade-off is less control over how/when the wasm gets compiled and instantiated. Or at least, the existing bundlers I've seen don't seem to give that kind of control. I'm also seeing different APIs from the different bundlers. E.g. wasm-loader exports a different API than your wasm2es6js. So there's some danger of becoming dependent on a particular bundler.

But those questions aside, the latest code is working great otherwise. So I'm happy leaving this one closed. And I'm excited to see where the library goes from here. All cool stuff!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants