Btw, I am very bad at naming, I chose the name cause it has most of the letters that "JS-WASM" has (or all of them if you consider W is just inverted M)
Is this true? Rust is hyped like crazy and seems to be used everywhere these days.
We were actually hiring for a couple of roles, although we just sent out two offers, so we won't be if they get accepted.
A wasm runtime can be far more lightweight than node, not only because node itself is a wasm runtime, plus a lot of other things. Wasm could (or does, already?) occupy a sweet spot where platform independent extensibility is desired, but where that is not enough of a core feature to make inclusion of a heavier runtime advisable. Kind of like how Lua has its place, but with more focus on near-native speed and less focus on ad-hoc programming (aka scripting).
With regards to porffor. It's a very good project and people behind it are probably much better at writing interpreters/compilers, but the biggest difference is in what WASM features the projects use. porffor uses only core WASM, which means they have to implement a lot more features themselves. Data types like arrays, structs/objects, garbage collection, exception handling etc. I am using WASM features added in proposals standardized very recently, like WASM GC or exception handling, which means I get a lot of the features almost for free. And I suppose that's also why semantics like scopes/closures are really hard to do for projects like porffor or even AssemblyScript and were relatively easy in Jaws.
The trade off is mainly in support. porffor compiled binaries can run on a lot of different WASM runtimes, I think there are even some runtimes for Core WASM for embedded devices. In case of Jaws, the runtime needs to support the proposals I use. Currently there are only two runtimes, that I know of, supporting both WASM GC and exception handling: V8 and WasmEdge. I believe more runtimes will get there, like for example WasmTime people are working towards exception handling, but it will take some time. Which is not a problem for me, cause it will definitely take a bit to reach any production level JS compatibility - I think the runtimes will have time to catch up with the proposals by then.
Do you have the results of test262_runner.rb? I came to know about test262 at a talk by the porffor's author and something like https://github.com/CanadaHonk/porffor?tab=readme-ov-file#tes... in README would be great to show this progress. Great project by the way!
Once I finish implementing `await` and generators, which are the last hard to implement semantic concepts, I will be implementing those low hanging fruits. It's hard to say how much coverage that will give me, but just to give an example: currently 1200 tests fails, cause `object["foo"]` syntax is not implemented. Ie. `object.foo` works, but `object["foo"]` does not. It doesn't mean that those 1200 tests automatically will pass, cause they might be testing other stuff, but there is a lot of such relatively simple syntax ommissions that make hundreds of tests fail.
And yes, I would love to have a nice graph like porffor has! :D
Does it support ArrayBuffers?
https://www.microsoft.com/en-us/research/uploads/prod/2019/0...
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).
WASM specifies UTF-8 for the encoding of names in its file formats, but that doesn't involve the runtime VM.
Thank you for working on this! I think it’s a great idea.
Very cool and interesting project! How are build times? And how big are the artifacts?
I'll for sure keep an eye on this, and add it to my ever expanding list of tech to explore.
Thank you for sharing!
One interesting thing is that `eval()` support will require custom WebAssembly host functions, cause you can't do custom code generation in WASM. Thus by default the project will assume "no eval" compilation. In this mode it will be possible to do a lot of optimizations, like for example remove unused parts of the language/types, do certain optimiztions knowing exactly what types the script is dealing with etc. So a simple script that doesn't use a lot of the builtins should eventually result in a fairly small binary.