|
|
|
|
|
by OscarDC
593 days ago
|
|
I read the README.md of the project but I'm still not sure: What's the expected usage of this? How does the outputed WASM code then interacts with a runtime (and with which, is it intended to be a tool compatible with browsers and other WASM runtimes or is it only compatible with a runtime linked to the project)? Somewhat linked questions: How does it react if it encounters e.g. web APIs inside the JavaScript code or other global identifiers only defined in some environment (e.g. a recent browser, Node.js etc.)?
Or if it's not intended for those environments, how are you supposed to do I/O when using this? |
|
This is all due to a fact that historically WASM was a very simple runtime. It was relatively easy to compile C code to WASM, just like you compile C code to machine code, but even though a WebAssembly is a kind of interpreter by itself, it wasn't easy to interpret higher level languages on top of it.
With new proposals being standardized, like garbage collection support or exception handling support, WebAssembly becomes much more powerful interpreter, with stuff like structs, arrays, function references etc.
Jaws leverages that fact translating JS code to WASM code in a way that WASM interprets the resulting code, without the need of a JS engine like SpiderMonkey. In practice it mainly means that a binary generated by Jaws will be probably under 50KBs vs 10MBs when you compile SpiderMonkey to WASM and run your script on top of that. Memory usage will be also significantly lower. For companies like Fastly this would mean orders of magnitude lower memory usage and thus server costs. For companies like Shopify it would mean they could leverage JavaScript code already available (think NPM packkages) and JavaScript ecosystem for people writing plugins for Shopify's backend.
> is it intended to be a tool compatible with browsers and other WASM runtimes or is it only compatible with a runtime linked to the project
The only runtime the project uses is WebAssembly. The generated code is mostly 3k lines of WAT code form this file: https://github.com/drogus/jaws/blob/main/src/wat/template.wa... and whatever your JS code is translated to. For example for a very simple program like "console.log('foo')" the entire "generated" part is this: https://gist.github.com/drogus/1c49c25ed0b14804b2f27e10d2a79..., which more or less prepares an argument (with new_static_string) and then calls console.log. Right now I need a bit of glue code on the host, but eventually it will be possible to execute such a binary with any runtime that supports WASIp2, WASM GC and exception handling proposals.
> Somewhat linked questions: How does it react if it encounters e.g. web APIs inside the JavaScript code or other global identifiers only defined in some environment (e.g. a recent browser, Node.js etc.)? Or if it's not intended for those environments, how are you supposed to do I/O when using this?
None of this is implemented yet, but I can tell you how it will work. I plan to support Node.js APIs through WASI. WASI is a standard for communicating between WASM programs and the outside world. For example WASI defines a standard set of functions you can use to send an HTTP request, or write to STDOUT, or read/write to a file. So when I get to APIs like `fetch` or `fs`, it should work with any runtime that supports WASI preview2. Browsers could also be supported with polyfills, but in this case I/O support is more custom. Like, if you decide you allow WASM programs to write or read files, you would have to provide a mechanism to do that, for example save files to localStorage or an SQLite database compiled to WASM (or I guess even send them to S3 or something along the lines).