I can AOT compile a complete binary, and can run on (just about) any target.
If I want to implement asm.js, I have to implement a full JavaScript JIT (if I want decent performance). This is Hard. I can't AOT compile, by the nature of JavaScript.
So, no, there is a difference. One of these technologies brings the entire bloated browser technology stack along with it, and one finally cleans up that bloat.
What makes asm.js "insane" by comparison? The syntax?
There's a bytecode for asm.js too if you want it. https://github.com/kripken/emscripten/wiki/Emterpreter
> If I want to implement asm.js, I have to implement a full JavaScript JIT (if I want decent performance). This is Hard.
Writing a compiler that gets decent performance for LLVM is also Hard. (Go look at the size of the x86 backend alone in LLVM.) If you were writing an asm.js engine from scratch with no support for any JS other than Emterpreter bytecode, asm.js is probably even a bit easier than supporting PNaCl, due to the lack of types and no SSA. But honestly, the amount of work you need to parse a different bytecode doesn't matter much compared to the amount of work you need to do to write a good compiler, which you would have to do either way.
> One of these technologies brings the entire bloated browser technology stack along with it, and one finally cleans up that bloat.
Except that, as I mentioned above, you're never going to "clean up" the stack. HN, which you're using to post this comment, hasn't even moved beyond the <font> and <center> tags; what chance is there for browsers to drop all that technology when many sites haven't even adopted CSS1? The difference isn't between "HTML + CSS + JS" and "alternative stack", it's "HTML + CSS + JS + asm.js" and "HTML + CSS + JS + alternative-stack-that-duplicates-the-features-of-the-previous-three". You have to take that into account when talking about the complexity calculus.
Firefox AOT compiles asm.js. All you have to do is validate it (like you would any other bytecode) and then you can in fact AOT compile it. You don't even need a full JS parser, since asm.js only uses a subset of the syntax allowed in JS.
Also, both are based on single-vendor, single-implementation technology. NaCl used actual native code, so if you're not using x86-64 or ARM, too bad! And PNaCl uses LLVM, so there's only one implementation.
Compare this to asm.js. It's a strict subset of ECMAScript/JavaScript, which has several high-quality implementations, and is portable across platforms. It uses the existing standard web APIs, which also have several high-quality implementations.
It's still wasted effort, though. Maybe they share some code, but Pepper is an unnecessary extra API. One that's non-standard and results in vendor lock-in.
The general consensus among non-Google browser vendors was that just using the existing browser APIs was a more desirable approach than Pepper. Since then, Pepper has remained a Chrome-specific technology.