As an implementer of WASI, I applaud this. Also, we are using wasi-testsuite and plan to contribute to it as Wizard finally has a full-time project for WASI.
If you mean at the bottom of the wasm, the the answer is, those won't be legacy APIs. The direction we're heading is to provide POSIX compatibility as an emulation layer on top of a cleaner foundation, rather than just doing POSIX at the base layer.
If you mean that all Wasm engines today are implemented on top of traditional operating system APIs, then yes, that is how things will often work, but that's ok. What really matters is how the virtual platform works. We don't have to expose things like "the filesystem namespace" directly to wasm, even if it's present in the host. And if we don't expose "the filesystem namespace", then we don't have the associated problems, even if the underlying host has them.
> The direction we're heading is to provide POSIX compatibility as an emulation layer on top of a cleaner foundation, rather than just doing POSIX at the base layer.
What's that "cleaner foundation"?
Next thing is: POSIX is the legacy stuff. If it's there nothing will change.
And not even to mention that the stack is going to look something like:
Hardware >> Hardware emulating some ISA (e.g. x86) >> C abstract machine >> POSIX >> VM emulating some ISA >> "container" emulating POSIX >> WASM VM >> emulation of POSIX APIs >> legacy applications written for some ISA & POSIX
That cleaner foundation is shared-nothing linking, capability-based security, virtualizable APIs, and more, and a WASI organized around things like streams as first-class types.
The goal is to build a new platform. Initially, that looks like adding layers on top of existing platforms (which, as you say, already have multiple layers). If we succeed, then we get to start taking out some of the layers.
It does, but that opens up much more powerful tools to work with.
As an example of one such tool in practice, compare the task of "list all open file descriptors in an arbitrary Unix process" with "list all strings an arbitrary Unix process incorporates some knowledge of". One is a one-liner (`lsof -p <pid>`) and one is really tricky at best, and probably can't be done reliably.
Typing is nice, and when one is working within an existing system where environment variables are the main way for communicating data between parts of a system (which is many popular systems today), this kind of typing looks like it can add some nice benefits.
The blog post linked here is thinking about how the systems themselves could be designed differently, whether that's OS's, frameworks, platforms, languages, clusters, networks, or other things.
In systems designed for it, communication channels can transmit handles without using a shared namespace or master list. An example of this in the real world is Unix-domain sockets having the ability to send file descriptors across the socket without using a namespace or master list.
There are IPC mechanisms today which aren't just bytes. For example, the ability to send file descriptors over unix-domain sockets. Strings of bytes fundamentally can't do that. And in programs that pass file descriptors, it doesn't require any ghostly assumptions about what namespace the strings need to be resolved in.
To be sure, Unix-domain sockets aren't the answer to everything, but they are an example of a different way to think about communication.
Wasm is Turing-complete. What people typically mean by this is that in a browser context, compiling JS to Wasm does not currently make it run faster than just running the JS as JS.
Javascript can be compiled to WebAssembly, and there are people doing it:
This is true, however if we modify the program to print a 4096-byte long string instead of just the "hello world" string, then it's not sufficient again. And of course, the number 4096 is system-dependent.
So to really do hello world in C right, in addition to fflush, you also need to check the return value from puts. I've never seen any C tutorial do that though.
Because errors on FILE streams are persisted until clearerr, it should be sufficient to check the return value of fflush at the end of the program. Presumably the FILE I/O interface was deliberately designed this way, so error checking could be consolidated at the end of a series of operations.
What would be the expected reaction if either puts or fflush returns an error code? You might think, write a message on stderr (which may be different from stdout), but what if stderr is also redirected to a full device? How would you react to the error code returned from that?
To me this is an indication that you need to know the context in which the program gets run, and its purpose in that context. Or you'd have to specify every edge case, but I've never seen that really work in practice.
> What would be the expected reaction if either puts or fflush returns an error code? You might think, write a message on stderr (which may be different from stdout), but what if stderr is also redirected to a full device? How would you react to the error code returned from that?
I don't think you would react any differently on stderr failure unless you had a more complex system with alternate ways to report such things configured.
Just ignore it and continue to report the major error (stdout) in your exit status.
Amazing!! Rust safety all the way up to the Linux system calls, and no legacy cruft like errno anywhere. That's the sort of project I had in mind. I'm so glad I'm not insane for imagining things like this. It would be so great to see a 100% Rust or Lisp or Zig user space built on top of Linux. Would be a lot more interesting than the same old POSIX user space every distribution ships with...
If there's community interest, there is a possible path where Mustang matures to the point where it makes sense to talk about how to incrementally migrate the parts that make sense into Rust proper.