Jaws is an experimental JavaScript to WebAssembly compiler, crafted in Rust, that aims to generate efficient standalone WASM binaries. While still a work in progress, its goal is to support complete JavaScript functionality without reliance on heavy interpreters. Join the exploration towards a more versatile WebAssembly landscape.
Jawsm: Convert JavaScript to WebAssembly Efficiently
Jawsm (pronounced like "awesome") is a cutting-edge JavaScript to WebAssembly (WASM) compiler, expertly crafted in Rust. This innovative tool allows you to produce a standalone WASM binary that runs efficiently, without the need for an interpreter. While still in its experimental phase, Jawsm is poised to support the complete JavaScript language as development progresses.
Why Choose Jawsm?
Embarking on the Jawsm project stemmed from my experience creating a stress testing tool called Crows, which runs WebAssembly scenarios. I observed that existing solutions primarily supported code compiled from Rust to WASM. I recognized the need for a solution that could accommodate JavaScript, a language known for its ease of testing and flexibility. However, the challenge lies in executing scripting languages in WASM—typically requiring either a bulky interpreter or a language variant like TinyGo or AssemblyScript.
The vision for Jawsm is to implement 100% of JavaScript features directly in WASM without the overhead of a compiled interpreter, leveraging modern WASM proposals to make it a reality. If this resonates with you, please consider sponsoring my work.
Current Functionality
Initially, Jawsm focuses on implementing JavaScript semantics to ensure a strong foundation. Here are the features currently supported:
- Closures and scopes (with mostly accurate implementation)
- Basic error handling with
try/catch
- Limited
Promise
API and support forasync
Example Code:
Here’s a sample code snippet that showcases the error handling:
let value = "foo";
async function foo() {
throw value;
}
foo().then(
function () {},
function (v) {
console.log("error", v);
},
);
Additionally, Jawsm currently supports:
- Variable declarations (
var
,let
,const
) - Control flow statements (
while
) - String and number literals with basic operations
- Array and object literals
- The
new
keyword for object creation
Host Requirements
To ensure smooth functionality, Jawsm incorporates several recent WASM proposals. However, the generated binaries currently lack portability across different runtimes. My primary focus is to align with WASIp2, targeting Wasmtime for runtime execution.
For development and testing, I utilize V8 (via Node.js) with a JavaScript polyfill to accommodate necessary WASIp2 features. The accompanying run.js
script aids in executing binaries produced by Jawsm.
Future Directions
The roadmap includes resolving "hard to implement" features, beginning next with generator functions and the await
keyword. My intent is to use the stack-switching proposal—currently in Phase 2—for these functionalities, pending broader runtime support.
How Jawsm Works
Jawsm translates JavaScript syntax into WASM instructions, utilizing proposals like WASM GC and exception handling to optimize performance. The translation encompasses approximately 3,000 lines of WebAssembly Text (WAT) code, facilitating the conversion of JavaScript semantics into WASM effectively.
Example of Scope Management:
Consider this JavaScript script:
let a = "foo";
function bar() {
console.log(a);
}
bar();
Jawsm manages scopes by simulating JavaScript’s scope behavior within WASM, ensuring the function bar()
has access to the variable a
as intended.
Support the Journey
This project thrives on community support. If you’ve benefitted from Jawsm, consider checking out the contributions from the supporters who make this journey possible. Thank you for your encouragement!