TBH, I doubt it, writing "high level" Rust requires a too big "runtime portion" (in the same sense of "runtime" as the stdlib in C++, which also tends to bloat up executables), while "embedded style" minimal Rust without such a "runtime part" is so low-level you could just as well write C code (which is also "memory safe" in that environment because of WASM).
And even in the best case, a WASM blob still has a hard time beating a bit of Javascript if it is just used to glue a couple of browser APIs together (and in such a situation, the good or bad qualities of that "glue language" don't matter much).
Hybrid JS/WASM applications make a lot more sense, where some small performance-critical parts are implemented in WASM in a "runtime-free language", glued together by Javascript (similar to how python is often used as glue between functionality implemented in native DLLs).
Are you in the habit of using Rust + WASM? From how you’re wording this, I suspect not. Rust really doesn’t require a large runtime (until you do something that requires Unicode tables, then you pay a certain tax), and the difference between high-level and embedded styles is normally small to nothing—the whole concept of zero-cost abstractions is normally talking about performance, but correlates extremely strongly with code size too; such abstraction layers typically compile out of existence.
Also there’s still a fairly big difference between a more frugal style of Rust and C. Just because it can’t cause arbitrary code execution and the likes doesn’t make C safe to use.
Yes, when developing for the web people will hopefully pay a little more attention to binary size, because WASM does have a tendency to make big code blobs easier to produce, especially if you’re using generics liberally.
Finally, although at present the browser WASM story requires it to interact with the browser through JavaScript, that limitation is planned to be removed.
I have admittedly not much experience with Rust+WASM (I dabbled in Rust though), but enough with C and C++ on top of WASM, and the situtation is really quite similar to C++ (IMHO of course).
Theoretically, C++ also has no "runtime overhead", but start using high-level stdlib features, and suddenly there is a non-negligible overhead. It's possible to cut that down, but that requires a lot of "insider knowledge" of the compiler toolchain and the specific stdlib implementation. In the end it's always about deciding what C++ features to not use to cut the size down, and at the end of that process is a language that's essentially C (no generic containers, no automatically managed memory etc).
And even when using C it is non-trivial to cut down the overhead from the C runtime library functions so that it becomes "competitive" with minified Javascript doing the same thing.
Don't get me wrong, Rust's toolchain integration with WASM is excellent. But I wouldn't call Rust compiled to WASM a contender for killing Javascript.
> because WASM does have a tendency to make big code blobs easier to produce, especially if you’re using generics liberally.
WASM was designed to be compiled to very small binaries. The big code blobs you see are produced by the Rust compiler and are not a characteristic of WASM... just check the output of the Rust compiler for a hello world project in WAT format and you'll see it consists almost entirely of the memory allocator that's included in the binary...if you write the same code in WAT directly, or something like AssemblyScript[1], which is designed to use WASM primitives, it's going to be a few bytes for your typical WASM hello world.
I’m not talking about the constant overheads, but how WASM grows as you scale your code base. My experience is that in practice it tends to be grow a little faster than equivalent JavaScript, say 1.2–2× the size depending on what you’re doing. But I should definitely have clarified that I was speaking specifically in the context of Rust—my generics remark certainly only makes sense in that context.
It’s not fundamentally terribly much larger, and can definitely be smaller (again, depending on what you’re doing), but using it as a compilation target makes it much easier to produce binaries larger than you anticipated. In JavaScript you distribute what you wrote, so you know if you loaded a lot more code. Well, in theory. Code bundlers and liberal importing of third-party libraries kinda put paid to that.
WASM provides enough memory safety so that memory corruption errors in the WASM heap can't be used to escape the sandbox (assuming there's no exploitable bug in the sandbox itself of course). It doesn't protect from memory corruption inside the WASM heap of course.
A fun exercise would be compiling the Heartbleed version of OpenSSL into WASM.
Exploits can escape the sandbox, via functions exported from WASM that change their behaviour due to internal memory corruption, or callbacks that get called with unexpected parameters from the WASM code due to the internal memory corruption that changed the execution logic.
For example, a security system that would grant higher credentials than it was supposed to.
Yes it follows Harvard architecture, still you can produce exploits by corrupting memory, no need to rewrite code, it just becomes harder to achieve them.
Basically by corrupting memory, you can achieve that the executing path changes and what was false is now true, thus influencing the outcome of what gets called and their parameters, without having to change any byte of the code.
And even in the best case, a WASM blob still has a hard time beating a bit of Javascript if it is just used to glue a couple of browser APIs together (and in such a situation, the good or bad qualities of that "glue language" don't matter much).
Hybrid JS/WASM applications make a lot more sense, where some small performance-critical parts are implemented in WASM in a "runtime-free language", glued together by Javascript (similar to how python is often used as glue between functionality implemented in native DLLs).