Wasm Builders 🧱

gunjan agarwal
gunjan agarwal

Posted on • Updated on

Compiling Javascript to wasm

In this post, we will convert our javascript code to web assembly.
So, first let's setup our environment.

Local Environment Setup

1) Javy - A JavaScript to WebAssembly toolchain. It takes your JavaScript code, and executes it in a WebAssembly embedded JavaScript runtime.

In your terminal/shell clone the javy repository as follows:

git clone https://github.com/Shopify/javy.git
Enter fullscreen mode Exit fullscreen mode

Now, navigate to javy by executing cd javy
Here, you have to install all the build and development dependencies in javy directory from here.

After all the dependencies are installed, run make. You should now have access to the executable in target/release/javy

Alternatively you can run make && cargo install --path crates/cli. After running the previous command you'll have a global installation of the executable.

2) Wasmtime - A small and efficient runtime for WebAssembly & WASI.
It can be installed by

curl https://wasmtime.dev/install.sh -sSf | bash
Enter fullscreen mode Exit fullscreen mode

Code

Create a javascript file named index.js and write js code for fibonacci number as-
We need to call our main function i.e., fibonacci in our case, from the shopify object.

//Simple Program to calculate Fibonacci Sequence of an Integer Input
function fibonacci(num){
  var a = 1, b = 0, temp;

  while (num >= 0){
    temp = a;
    a = a + b;
    b = temp;
    num--;
  }
console.log("Fibonacci Term is ",b);

}

var Shopify = {
  main: fibonacci
};
Enter fullscreen mode Exit fullscreen mode

Compiling our code

1) Convert javascript code to wasm binary

javy index.js -o index.wasm
Enter fullscreen mode Exit fullscreen mode

2) Execute wasm file, using following command

echo "10" | wasmtime run index.wasm
Enter fullscreen mode Exit fullscreen mode

You will see the output:

Output file

References - https://www.wasm.builders/deepanshu1484/javascript-and-wasi-24k8

https://enarx.dev/docs/WebAssembly/JavaScript

Top comments (11)

Collapse
 
webcoder profile image
WebCoder

Thank you, @gunjan_0307 . Are there any good reason to use this approach? Because if you want to run JavaScript without a browser, you can just use NodeJS.

Collapse
 
nick profile image
Nick Vidal • Edited

That's a good question, @webcoder. So one key reason would be security. Since WebAssembly uses a sandbox model, you can prevent a malicious or buggy JavaScript application from compromising the host. Other reasons might be performance and portability. Depending on the application, it might be faster to run the WebAssembly code directly (no Nodejs overhead). As for portability, you might run this same application anywhere without recompilation (server, client, edge, IoT, whatever).

Collapse
 
gunjan_0307 profile image
gunjan agarwal

@nick Thanks for so good explanation. :)

Collapse
 
salimf profile image
SalimF • Edited

For me, it was simply getting byte code off my JavaScript files, it's like dream comes true.

Collapse
 
developerworks profile image
developerworks
t@iZj6ceuntkc5q6r6ip9tdaZ:~/demo# json2msgpack -i input.json | wasmtime run index.wasm | msgpack2json
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: EOF while parsing a value at line 2 column 0', crates/core/src/main.rs:51:72
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Error: failed to run main module `index.wasm`

Caused by:
    0: failed to invoke command default
    1: wasm trap: wasm `unreachable` instruction executed
       wasm backtrace:
           0: 0x11167 - <unknown>!<wasm function 191>
           1: 0x19631 - <unknown>!<wasm function 316>
           2: 0x11ce - <unknown>!<wasm function 24>
           3: 0x18df - <unknown>!<wasm function 30>
           4: 0x9c05 - <unknown>!<wasm function 125>
           5: 0x961d - <unknown>!<wasm function 123>
           6: 0xbd0d6 - <unknown>!<wasm function 1165>

msgpack2json: parse error: mpack_error_io (2
Enter fullscreen mode Exit fullscreen mode

What is the issue about this errors follow your article.

Toolchains:

DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.3 LTS"

rustup 1.24.3 (ce5817a94 2021-05-31)
rustc 1.60.0 (7737e0b5c 2022-04-04)
cargo 1.60.0 (d1fd9fe 2022-03-01)
wasmtime 0.36.0
cargo-wasi 0.1.23 (aa58e595d4 2021-07-29)
cmake version 3.16.3
Enter fullscreen mode Exit fullscreen mode
Collapse
 
gunjan_0307 profile image
gunjan agarwal

There has been some issue with the recent release of the Javy Toolchain as pointed by @deepanshu1484 i.e., There has been some changes in the way in order to make it work on Wasmtime and we do not require the use of msgpack-tools anymore and thus the process has even become more convenient now.
I have update this post, please have a look.
Thanks.

Collapse
 
developerworks profile image
developerworks
Thread Thread
 
gunjan_0307 profile image
gunjan agarwal

Yes I also followed his demo 😀

Collapse
 
spookyvision profile image
Anatol Ulrich

this is super exciting stuff - any idea why wasm-opt can hardly shave off anything in terms of size? (getting 992k vs. 982k for a very simple js file, essentially just a bit of math and console.log)

Collapse
 
cosmin_s profile image
Cosmin S

probably because of the bundled runtime (which includes a gc)

Collapse
 
hdv2b profile image
Hussein Duvigneau

Unfortunately for me, Javy explicitly doesn't support Node.

My problem is I'm using a js library in the browser. This lib was specifically built for node, but later added support to run in browser via a patchwork of polyfills. The lib does run OK in node. Not blazingly fast, but acceptable, while in the browser the same script (running in a web worker) will take way longer for small data, and hang indefinitely with large data (large data that wasn't a problem in Node).

So I'm hoping I can compile the script from Node to WASM and ship it to the browser and get the same performance as if it were running in Node.

As someone new to WASM, does this sound sensible?