Transpilers and the future of js

2011-05-20 18:30:54

From the language perspective transpilers (or transcompilers) are actually awesome. And although the term was new to me when Brendan put it in his slide at JSConf two weeks ago (google says it's older), the principle is of course not. You translate one language into another. Just like whenever you write C code, it gets translated into machine code by the compiler. Whenever you write JAVA, it gets translated into JVM byte code which in turn is executed (and therefor translated) into machine code.

In the context of JavaScript, transpilers are apps that cross compile one language into js or js into another language. The past year we've seen a lot of these transpilers. A big example is the Emscripten LLVM compiler which compiles LLVM into js. Demo results of LLVM are a pdf viewer and the Lua interpreter, and they work nicely too. And of course Coffeescript emerges, which is a language that's a superset of js and that compiles into js. There's actually a huge list of transpilers, which is a little mind boggling.

The release of a x86 emulator in js that runs Linux this week marked a new height in this area. It runs Linux in your browser. The author claims it runs at about the speed of a 486 right now. You know how awesome that is? Man... And since it runs linux, it basically runs anything that runs in Linux and by proxy, that runs pretty much anything that doesn't depend on specific hardware.

But that's not surprising. JavaScript or ECMAScript is a Turing complete language. This is a set of languages that could do anything that a Turing machine could possibly do (this includes most programming languages, including C and Java). In fact, the Linux compiler proves this point very explicitly :)

So I think this is the future. JS is a very popular language right now. I'm too lazy to back up claims like "the most popular language", but I think it's safe to say that it's very popular. And more importantly, the environment is available on a lot of platforms, including most mobile platforms. This makes it very easy to create code, distribute it through a website and share it with pretty much anyone on any device.

Transpiling from/to js will happen more often. I foresee a future where the browser has an API where you can ask it whether it supports a certain language. If it does, just download the source and let the browser run it natively (which should be faster). Otherwise, load up the runtime transpiler (or pre compiled js result) and run it through js.

For instance, you could ask the browser whether it supports running Lua, in a compatible version, and if so have it load the correct script. Otherwise it loads the pre cross compiled js version of the code. Or maybe load the cross compiler itself and cross compile on the fly.

Mozilla is already making the first steps by adding a pragma that allows you to debug your cross compiled code more easily. The pragma would tell the browser that the current line is actually line x in the real source. This is important because the cross compilation obviously results in a different code where line numbers do not correspond with the original source any more (although come to think about it, you could probably build js in such a way that every line does correspond with the original source because you can single line any set of statements...).

And you know what, it's awesome! JS will move to something like a JVM language (and yeah, I know not everyone favors that) and "web developers" can just pick their own poison. That's important because not every developer loves js but right now they have little choice (although that choice is expanding with the list of transpilers ;).

The path I described above is not here yet. For instance, I've not heard of the described API yet from anyone else. And even if becomes adopted, it will take a long time before it's actually generically usable. Of course you could easily create some kind of fallback syntax for it. Just from the top of my head, something like:

Code:
<script src="compiled-code.js" if-lang-supported="lua" if-lang-version="4.x" if-lang-src="code.lua"></script>

So if the browser supports the language api and supports Lua version 4.x, ignore the original src attribute and load code.lua in the interpreter instead. If the browser doesn't support the requested language, language version or the language api in general, the extra attributes would be ignored and src is used as it would be now. Bikeshed on syntax all you want, it's just an example.

Of course there are some potential issues with this. Most notably there's a security issue here. JS has been carefully crafted to be safe in the browser context. And that's taken about ten years to get decent. Now imagine you'd have direct access to a Lua environment. Suddenly code has access to all kinds of things you might not want websites access to. You'd have to create a very "secure" sand box for each language before opening it up to the web. That's obviously not an ideal situation. So that might actually be a show stopper. Transpiling the same language does not have this problem because regardless of what the language would allow you to do, the governing environment (js) still imposes the restrictions required for the web. And there's no way to break that, unless you could already with just js (so no way to create new buffer overflows in the browser with cross compiled environments, for instance).

Of course browsers could at least offer a "native" transpiler for certain languages, using the same kind of api. That could be interesting if native support is not going to happen.

But yeah, the general principle of loading all kinds of languages in the browser is going to happen. Maybe not natively per se, but at least through js. And still it performs fine for most use cases :)