rustwasm / wasm-bindgen

Facilitating high-level interactions between Wasm modules and JavaScript
https://rustwasm.github.io/docs/wasm-bindgen/
Apache License 2.0
7.72k stars 1.06k forks source link

wasm2js example outdated and not working as expected #2428

Closed nicolasmelo1 closed 3 years ago

nicolasmelo1 commented 3 years ago

Summary

Hello, so i'm trying to run wasm in react native and since i cannot run webassembly code directly i thought about creating a wasm file, converting it to JS using wasm2js command and then using the generated file directly. Before testing in the react native ambient i'm making tests directly in the browser and for this case i'm using the wasm2js example provided in the wasm-bindgen examples folder. But following the EXACT steps defined by the example, the wasm2js is STILL fetching the original .wasm file and not using the .js file generated by wasm2js command

Expected Behavior

In reality, if i understood correctly the wasm2js.js should use thewasm2js_bg.js file and not the wasm2js_bg.wasm file. Since some browsers might not support WebAssembly.

What happens is that this command in build.sh

sed -i 's/wasm2js_bg.wasm/wasm2js_bg.js/' pkg/wasm2js.js

is doing nothing in the pkg/wasm2js.js file

Additional Details

So to make it absolutely clear here what i'm trying to do is:

1 - Create a rust package that should be used both by the browser and the mobile version of my app 2 - On the browser i'll use the .wasm directly with webpack 3 - On the mobile i'll convert the .wasm to JS so i just use JS code instead of .wasm code. (performance penalties are known but the core idea here is to be possible to use my rust functions already created without needing to rewrite it in javascript) 4 - On step 3 i'm not testing this already in the app, but instead i'm making tests directly in the browser, i want to run the example code using only the .js files and not fetching the '.wasm' as it is doing by default

STEP 4 is basically what i need to reproduce and facing issues with.

I've tried running the wasm2js generated .js file directly, the problem is that they import 'wbg' which is defined in the wasm2js.js file, so it's not working.

alexcrichton commented 3 years ago

Hm sorry it's been quite some time since I looked at this example. It could be an issue with the example, but can you track down where the fetch of the wasm is happening? Perhaps you can work backwards from there to figure out where the issue is and what's not requesting the JS instead?

nicolasmelo1 commented 3 years ago

Hello, thanks from the response in advance.

So from what i saw

input = import.meta.url.replace(/\.js$/, '_bg.wasm');

on this line in init() function is the exact line the where it gets the route to the .wasm file and here

is where it fetches for the .wasm file. i've tried changing this

but still it didn't work as expected. Because it's still trying to create a WebAssembly intance in load, as you can see in load function in the js output it doesn't handle when there is no WebAssembly available in the browser

on the '.js' file created by wasm2js it imports the wbg module, but since this module doesn't exist, i haven't found a way to make this file work with the wasm2js.js file outputed by the wasm-pack build

alexcrichton commented 3 years ago

Oh the wasm2js support was intended to be used with ES modules, I don't believe it works with --target web or no-modules since they use the WebAssembly object for instantiation which won't work.

nicolasmelo1 commented 3 years ago

That's actually strange because on the example in the build.sh on the second line we compile targeting to --target web

But anyway, i've tried running

wasm-pack build

And it gives me two .js files:

Then i run the following command to create a new .js file from the wasm wasm2js ./pkg/wasm2js_bg.wasm -o ./pkg/wasm2js_bg1.js

in the wasm2js_bg1.js file we end up with

import { __wbindgen_throw } from './wasm2js_bg.js';
// ... rest of code generated by wasm2js

and in wasm2js_bg.js which was generated by wasm-pack build i've changed:

import * as wasm from './wasm2js_bg.wasm';

to

import * as wasm from './wasm2js_bg1.js'; // file generated by wasm2js command

and now we end up with a circular import.

How i solved for my use case

For my use case i was able to prevent this from happening by removing this import in wasm2js_bg.js and using require('./wasm2js_bg1.js') whenever wasm was being called in wasm2js_bg.js

So i've changed this:

But i don't think this is a good solution, especially if the idea is to target browsers which doesn't support require()

mvniekerk commented 3 years ago

I've got the same issue, also with same MO (Rust -> WASM -> JS -> React Native). git@github.com:mvniekerk/brotli-rs2js.git

I'll be following @nicolasmelo1 's example and try get it running.