Hard to say at this point, but I really doubt it will be ever faster than SpiderMonkey or V8 with JIT enabled. Modern JavaScript compilers are quite good at optimizing hot paths through JIT. The use case of this project is to be able to run JavaScript in WebAssembly sandboxed environment. Like, for example Shopify allows you to extend their backend code using WebAssembly, but there is a binary limit capped at 250KBs. At that size you can't really use JavaScript at the moment, cause even simple interpreters like QuickJS take a few MBs compiled to WASM.
I haven't seen Static Hermes before, I'll take a look, thanks for the link!
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.
I haven't seen Wasmnizer before. This looks like a cool project and I'll be definitely taking a closer look when I have some time, but for now I just took a quick peek.
The main difference is obviously TypeScript vs JavaScript. Because they are not bothering with JavaScript, some stuff is much easier, like for example if a function specifies an argument as `number`, you can statically compile it to use a type representing a number (possibly even without heap allocations) instead of passing something like `anyref` everywhere and doing typechecks.
The second big difference is that they seem to use types imported form the host. This means they can implement part of the types/builtins/methods on the host (which is easier, cause in JavaScript you simply use JavaScript for defining host stuff) at a cost of doing more calls from WASM to the host. And then you need the host to implement those functions (here is an example for JS host: https://github.com/web-devkits/Wasmnizer-ts/blob/main/tools/...). My plan for Jaws is to only rely on WASI, so that you can run your program on any runtime that supports WASI.
I'm also not sure about their approach to semantics. I can't quite grasp how they implement for example scopes. I tried to compile a small TS script that relies on scope, like:
let message: string = 'Hello, World!';
function test() {
console.log(message);
}
test()
And the result was console.log printing null. I'm not sure if I'm doing something wrong or is it expected, but I'll ask them in an issue later.
Do you have any plans to be able to take TypeScript types to do type optimizations? That sounds like a bonus to me to be able to have easier implementation and faster run times.
Yup, that's something that I would definitely like to do. In performance critical applications adding type information can speed up things quite a lot, especially when you think about numbers. At the moment I have to pass numbers as structs with one f64 field, because an argument to a function in Javascript can be any available type. If the type is specified, the signature or return type can use f64 types directly and don't even do heap allocations. But even for heap allocated types it may result in better performance, cause at the moment for each object I have to check what type it is and what path to take in order to proceed.
Good luck! I’m interested in seeing how JS to WASM compilers can speed up edge rendering use cases. WASM opens the possibility of really cheap request isolation, far faster than process forking. But JS interpreters in WASM are currently so much slower that they still lose out performance wise overall.
Hyped and visible on socials doesn't necessarily mean it's widely used, but I guess it also depends on how you define widely. According to most stats I've seen Rust usage is maybe about 5-10% of languages like JavaScript and Python when you look at StackOverflow, indexes like PyPl, or GitHub statistics.
Which puts it already in the second tier of most used languages with big guys like Java, C#. I think Rust will soon join the ranks of JavaScript, Python and C.
I have gut feel (perhaps only because my echo chamber includes the Rust Evangelism Task Force) that Rust/WASM is likely to become the go to stack for complex web apps.
Google (collectively) have written quite a bit about Rust adoption going back at least a couple of years. It'd kinda surprise me if there weren't some drive to write gmail/googledocs in Rust and deliver them as WASM. Meta/Facebook have some strong internal Rust evangelism going on.
I doubt it's a good idea, but it's likely my first trial "lets write a Rust project" will be an in-browser Rust/WASM thing.
> that Rust/WASM is likely to become the go to stack for complex web apps
What kind of apps?
On the backend there are plenty of mature ecosystems already that have been around for decades. Even focusing only on performance there's not a huge difference with say .NET or Java when looking at web benchmarks like TechEmpower[1].
On the frontend nothing can really beat the DX of using Vite with JS (hot reload of JS components, styles, etc). I don't know if it's even possible to get hot reload with WASM.
I could be wrong but it sounds like doing a complex web project in Rust would be a pain with not a lot of benefits over more popular and mature solutions.
Heh? I really like Rust, but it has absolutely zero advantage for this domain compared to the existing million choices. Unless you are doing some low-end web stuff with packets, any managed language will have a much better developer experience. Async rust is not particularly easy, and something like Java's virtual threads will give you both the ergonomics and the throughput, and then we haven't even talked about how much bigger the relevant ecosystem is (remember that the only order of magnitude improvement in dev productivity is from code you don't have to write)
Google has been doing it 2 decades ago with Gmail and the like. They could compile java to js. More recently, clojure and c#'s blazor come to mind that have the same ability.
In theory, the language might be a decent fit. But it’s not the language (mostly), it’s the library and ecosystem. Definitely not enough to unseat C++ yet for many new projects.
Rust is often used for things that you wouldn't necessarily use C++, though. Web backends (but mostly APIs at least as far as I've seen), CLI tools, various bots (like at my day job we have a Discord bot written in Rust) etc.
Rust holds a lot of appeal for web devs looking to leverage performance gains in build-time tooling (e.g. Biome replacing ESLint and Prettier) and bridging the native desktop gap (eg Tauri replacing Electron). There are more examples but those were front-of-mind.
Respectfully, I think your impression is mistaken. I gave specific examples of Rust adoption for webdev build tooling, but am not aware of any comparable Go equivalents. (When it comes to runtime services, that's another story, where Go has made more significant inroads.)
First of all, past performance is not indicative of future results.
Second, it's obviously much easier to double your user base from 2 to 4, than from 10 million to 20. New languages tend to have a fast initial growth, but then the curve flattens and no significant change comes after. Java hasn't been on a decline in the absolute sense, the whole market has just grown and has more players now, so the same mindshare gives less of a percentage now. Nonetheless, no language has come even close to the top 3 languages (js, python, java) in popularity that were released in the last 20 years, so what makes you think that Rust will be the one that avoids the flattening of its growth?
I'd like some references of "Java mindshare is going down fast".
Sure, lots of new project/code uses languages like Go these days. But Java is still very dominant, especially at companies like Amazon. It currently sits ar #3 on TIOBE.
thanks for reporting and sorry about that! I was prepending some JavaScript code to be compiled for test262 harness before, but at the moment it was just an empty file, so I removed it and pushed a fix. Please try again now and let me know if you run into any issues!
Yeah, at the moment it's passing about 12% of tests, but there is a lot of low hanging fruits to implement, especially considering I started the project two weeks ago. This doesn't mean I will hit 100% in linear time, unfortunately, cause there is a long tail of builtin types and functions, but as I started by implementing the "hard parts" I left some easy parts not done. For example I implemented only enough syntax to allow running conditionals and a while loop cause it was needed for the test262 harness, but I left all the other loops (for, for in, for of, do while) and conditional expressions (switch) unimplemented. Implementing them will be more or less analogous to existing implementations for if/else and while.
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
Yes now I'm looking at the tests I can see that the coverage won't increase linearly, but 12% (with some of the hard parts) in two weeks is impressive. I starred the repo, good luck with your journey :)
Not yet, it's very early stage where I'm mostly implementing full JavaScript semantics (and hopefully finding some funding/support for the project), but as soon as I'm done with async/await and a few simpler missing pieces, I will start implementing JS builtin types
reply