Hi all!
After reading some articles about WASM GC being a game changer for WebAssembly scripting languages support, I was slightly disappointed there are no implementations of JavaScript on top of WASM GC. I know there is porffor, which is a great and very interesting project, but it purposefully uses only core WASM. Honestly, I had no idea if implementing JavaScript semantics was possible even with WASM GC, so I did the only thing that made sense to me, I started writing the tool myself, to check it myself. I think it's going great, so I'm open sourcing it as Jaws
It's still very much an experimental tool, but I'm fairly certain it's possible to implement 100% of the JavaScript spec that way. In order to confirm it, though, I first wanted to explore implementing JavaScript semantics that are the hardest to implement: scopes/closures, try/catch, async/await and generators. I have the first two and the easier part of async/await (ie. async
).
To give you an example, this code will output the same thing that Node.js outputs:
let value = "foo";
async function foo() {
let bar = function () {
throw value;
};
try {
bar();
} catch (err) {
console.log("caught", err, "rethrowing");
throw err;
}
}
foo().then(
function () {},
function (value) {
console.log("error", value);
},
);
I'm now working on implementing await
and then generator functions. My current approach is to introduce CPS transforms into the code. I tried using Asyncify, but it looks like it doesn't work with proposals I'm using, so I'll probably just roll it out by hand (which also might be best anyway, cause there are some specific things I can do to make it fit the code I generate better). stack-switching proposal would be ideal, but I don't think any of the runtimes support it yet, so I'll leave it for now. It's hard enough to run the project anywhere even with the current set of WASM features :sweat_smile:
The project works as follows:
My plan is to use WASIp2 for stuff like handling incoming/outgoing HTTP requests, writing to STDOUT/STDERR and files, but also for using timers etc. WasmTime seems to be the only runtime supporting WASIp2/components, but unfortunately it doesn't fully support WASM GC nor does it support exception handling proposal, so I resolved to write a very simple Javascript polyfill for stuff that I'm using (only monotonic clocks and output for now).
Any critique, ideas, questions, or other input are welcomed!
Last updated: Dec 23 2024 at 12:05 UTC