-
Notifications
You must be signed in to change notification settings - Fork 783
wasm2js usage or usecase unclear #2263
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
Comments
It should work as you expect - it's possible you've found a bug. Do you have a testcase you can provide? One thing to note is that it by default emits an ES6 module. If your VM doesn't support that, it might give a syntax error on the module notation. If you don't want ES6 notation, see the |
Thank you for the quick response. What i'm specifically trying to get converted to ES5 javascript is a WASM compiled binary of a simple Go program:
The process of compiling Go to WASM is described in the official wiki here but i've also uploaded the resulting binary for download here. It comes in at a hefty 1.2MB because it includes the Go runtime but otherwise works fine when loaded into a modern browser using the following html: <html>
<head>
<meta charset="utf-8">
<script src="/internal/cmd/wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch("./main.wasm"), go.importObject).then((result) => {
go.run(result.instance);
});
</script>
</head>
<body></body>
</html> I then converted the main.wasm file to a js file like this import { runtime.wasmExit } from 'go';
import { runtime.wasmWrite } from 'go';
import { runtime.nanotime } from 'go';
import { runtime.walltime } from 'go';
import { runtime.scheduleTimeoutEvent } from 'go';
import { runtime.clearTimeoutEvent } from 'go';
import { runtime.getRandomData } from 'go';
import { getTempRet0 } from 'env';
var scratchBuffer = new ArrayBuffer(8);
var i32ScratchView = new Int32Array(scratchBuffer);
var f32ScratchView = new Float32Array(scratchBuffer);
var f64ScratchView = new Float64Array(scratchBuffer);
function legalimport$wasm2js_scratch_load_i64() {
if (typeof setTempRet0 === 'function') setTempRet0(i32ScratchView[1]);
return i32ScratchView[0];
} I then first tried to load it in chrome (as a start) by changing the html to: <html>
<head>
<meta charset="utf-8">
<script src="/internal/cmd/wasm_exec.js"></script>
<script src="/_examples/00-wasm2js/main.js"></script>
</head>
<body>
<div id="root"></div>
</body>
</html> This would give me the following error: If I remove the import lines that include the dot the javascript will fail with the same error Finally I ran wasm2js with the --emscripten flag ( What I think is happening is that WASM output is looking for functions that are defined in the helper javascript script called 'wasm_exec.js' (src) and tries to 'import' them in a way that is not supported? Maybe it possible to merge the wasm_exec.js with the output of wasm2js? I have some time to get this to work if you think it's feasible, what do you think? It would be really exciting to for the Go language and WASM as an intermediate format if we could get it to run on old browsers :) |
Yes, I agree it's exciting to get Go working in browsers (old or new) :) As an ES6 module, the full error looks like $ node --experimental-modules b.mjs
(node:234207) ExperimentalWarning: The ESM module loader is experimental.
a.mjs:1
import { runtime.wasmExit } from 'go';
^
SyntaxError: Unexpected token .
at Loader.moduleStrategy (internal/modules/esm/translators.js:51:18) The Go wasm file has imports with "." in the name, and those aren't valid JS identifiers. So the naive translation to JS doesn't work - those identifiers would need to be escaped, or the wasm not use such an identifier ("_" would be ok instead). Fixing that is one option. Another option is to use the non-ES6 output mode, that I mentioned earlier. Something like
Then the JS provides an I'd be happy to help out here, let me know. |
…ized. fixes #2263. Adds a complete example of usage in the readme as well
Looks like the first option, properly escaping such imports, is easy to do, I opened #2267 with a fix, and also some docs that include a full example of using wasm2js output. Ok, with that, I can run $ bin/wasm2js -O ~/Downloads/temp/main.wasm -o hello_go.js Then with these files it will load: <body>
<script type="module" src="hello_go.js"></script>
<script type="module">
import { run } from './hello_go.js';
run();
</script>
</body> // go.js
export var runtime_wasmExit = function() { console.log('exit') };
export var runtime_wasmWrite = function() { console.log('wasmWrite') };
export var runtime_nanotime = function() { console.log('nanotime') };
export var runtime_walltime = function() { console.log('walltime') };
export var runtime_scheduleTimeoutEvent = function() { console.log('schedule') };
export var runtime_clearTimeoutEvent = function() { console.log('clear') };
export var runtime_getRandomData = function() { console.log('random') }; // env.js
export var getTempRet0 = function() { return 0 }; ( I did need to edit With that, it seems to load and run! It calls those exports at least. (Those would need to be hooked up to |
Thats super cool! The README improvements definitely make it more clear and I got the setup you described to work. I'll focus on getting the go.js exports hooked up and report back. From there ill experiment with some more complex programs to see how far it goes. My initial question for this issue has been answered so you can close it if you want. I can open a separate issue to discuss further developments around getting Go programs to run |
@advanderveer great! Ok, let's close this, but please keep us updated on progress with this - I'd love to see it working! Docs or a blogpost about "how to use wasm2js with Go" would be cool eventually, happy to collaborate on that if there's interest. |
This fixes names that would be invalid in JS, like a.b. Turns out the Go compiler emits wasm with such imports. Also add some docs on how to use wasm2js. Fixes #2263
@kripken More than a year later I've finally came around to working this out a bit further! A proof-of-concept with a demo is available over here for anyone to check out: https://github.com/advanderveer/goes. I don't have a personal blog to post this somewhere but i'm happy to take feedback here on in the issues of the repo. Let me know what you think! |
@advanderveer Nice to see this work! Looking at it, some thoughts:
|
Dear reader,
I'm either using the wasm2js tool wrong or I don't understand what it should be use for. I'm pretty new to the wasm ecosystem so my apologies if i'm asking something crazy here.
Basically I got a
main.wasm
file that I run fine in browsers that support wasm directly. But I would like to research the possibility of running it in older browsers as well. The description of the wasm2js tool in the README.md seems promising "compiles WebAssembly to JS" and is also hinted at in the wasmrust documentation: https://rustwasm.github.io/wasm-bindgen/examples/wasm2js.htmlBut whenever I try to run the resulting .js file in chrome or node it will give me errors such as
Uncaught SyntaxError: Unexpected token .
. This seems to indicate it is not actually valid Js as expected by the browser or node. Is there an extra compilation step i'm missing? Some sources on the internet mention that the tool outputs "almost asm.js" but its unclear to me what I should do with this information. Issue #1929 and https://v8.dev/blog/emscripten-llvm-wasm#javascript-output seem to suggest the tool is moving away from asm.js... what gives?I'm building the wasm2js tool from source on the latest commit. But downloading it through the releases gives me the same mystery.
Any help on how to convert/transpile a wasm file to javascript that can be run in any browser would be appreciated.
Thank you!
The text was updated successfully, but these errors were encountered: