Some of these previous efforts might have one or two of these features, but none of them meet all of these criteria.
You seem to imply this approach wasn't successful before. IMHO it's been successful, more than once actually, just not awesome.
EDIT: you've since added some examples. Here are my (very subjective) opinions:
- The JVM isn't really all that low-level - it eeks out a lot of performance at runtime. Plus, you need to have GC, which tends to increase memory requirements and complicate real-time constraints.
- NaCL was interesting but its spec wasn't as good. IIRC Google didn't do too much in the way of asking for public input. I think some folks had some security concerns too. I really like WebAssembly's spec - I don't see any typing judgements or small-step rules for NaCL.
- Wasn't ANDF unix-bound?
Using bytecode as portable executable format has been a tradition in mainframes since the early 60's.
At its peak, there were many different vendors delivering JVM implementations. How we forget Kaffe, even.
* JVM - Most heavily used implementation borked the sandboxing. It also forces a GC down your throat, which is great for 95% of use cases, but the other 5% are really important too.
* NaCl - Really cool, but ultimately reliant on weird CPU features for protection. PNaCl was trying to fit a square peg into a round hole with the whole trying to make LLVM IR platform independent thing. WebAsm took a lot of ideas from these projects (and asm.js).
* P-Code - Really cool, but ultimately probably a victim of it's time. A little simplistic for modern architectures as it has no real concept of a memory model or atomic primitives.
* TIMI - Unbelievably proprietary. Even if you were to document it well enough to build an implementation, IBM would almost certainly sue you into oblivion.
And the reason running in a browser matters is that it guarantees a lot of teams will put effort into improving it.
some used to, until browsers banned them