Something like vim has archaisms that are only mildly depended on, allowing a project like neovim to credibly call itself the future. But Python 2 still has a large install base of software that's still running it. Python 3 didn't offer a smooth enough upgrade path from Python 2, so we're seeing the slow bifurcation of the community into two language. This also happened with Rails 2, there is still large enough install base of Rails 2 software that there's a dedicated effort to support it, Rails LTS.
These bifurcations will last until gradual enough upgrade paths are made and failure modes are isolated enough so that moving a project off of old tech and onto new tech can be accomplished without business investment. It's merely another user story to be put in the pipeline. Old applications will slowly get either abandoned or migrated or reinvented over time.
This process fails when you consider underlying infrastructure, which by its nature largely has a much deeper base of software that depends on it. Applications can have many dependencies, but those dependencies tend to be well-enumerated, as not enumerating them leads to a maintainability nightmare for people unfamiliar with the system. And nothing but other business software depends on the application.
But infrastructure code's dependency structure is inverted. Many more applications depend on infrastructure and infrastructure tends to have comparatively fewer dependencies of its own. When infrastructure has lots of dependencies it makes it harder to scale, and scale is the whole point of infrastructure. This need for infrastructure to all 'hang together' so as to provide for scale is what's behind the modern concept of an operating system. Applications tend to rely first on the software stack, second on the operating system. It's much easier take a Rails application built to run on Ubuntu and migrate it so it can run on Red Hat or Docker than it is to get it to run on Sinatra, god forbid another general purpose programming language. In fact, it's so much easier that it's considered a major red flag for this to not be the case. Operating systems are more fungible than software stacks.
This process of bifurcation followed by slow abandonment of harder-to-maintain systems in favor of easier-to-maintain ones is just going to slowly reach its apotheosis when line of business software that is much of a career programmer's bread and butter is going to slowly lose all attachment to, not just the operating system, but also the software stack as well. FaaS, Function as a service, is something you can add to your application right now, and once you do that work once, it just gets easier and easier to offload portions of the application that simply glue things together or compute things, to a magical land where teams of elves do literally everything else for you for a small fee, is going to become mainstream sooner rather than later.
I see wasm as a step towards this inevitability.
Then we have JVM, MSIL and DEX.
What would wasm bring that isn't already done?
What we haven't had before are architecture-independent executables that can be compiled into from a large number of programming languages.
So how many languages do they need to be to be considered large?
Don't take me wrong, I love those bytecode environments, including Web Assembly.
I just don't think Web Assembly is that much different from other ones, other than politics.
Look for IBM redbooks on IBM i and IBM z language environments.
How was the performance of the old mainframe formats?
The kernel has a JIT and they are converted into native code at installation time, or when an operator decides to retrigger the operation.
In a way, Android (5 - 7), iOS bitcode and WP 8.x MDIL follow similar ideas.
And something that I forgot, MSIL also has support for C and C++, hence why all C# 7.x performance improvements don't require any runtime change, just exposing features that C and C++ already make use of on MSIL.
The mainframe ones, are just like any other OS, code gets generated at installation time, then they are OS processes just like any other.
Java and MSIL depend on how they get used.
Both have bytecode verifiers, and multiple ways to deploy.
Either as single runtime, where strong typing plays the role of sandboxing, or as multiple processes/containers.
Just to use .NET as example, not going to make an exhaustive list.
.NET Micro Framework deployed on Netduino, the runtime is the OS, only strong typing takes place.
.NET Framework on Windows, and .NET Core on Windows/Mac/Linux, each CLR instance gets their own OS process, which might be additionally wrapped into an OS container.
.NET Core on UWP, applications run as separate sandboxed process using the UWP sandbox model.
Xamarin on iOS runs with the iOS sandbox model, after AOT compiling for deployment.
Xamarin on Android, runs with the Android sandbox model where binary code gets dynamically loaded into ART instance, sandboxed via SELinux and Linux container mechanisms.
And regarding security, Web Assembly still fails short of preventing memory corruption inside of the loaded module.
I was hoping pointers would be tagged, but that doesn't seem to be part of the design goals.