WebAssembly support


#1

Hi,

Since new slides about WebAssembly has been published, with the first release (Minimum Viable Product) planned this summer, and a standardization (I think this is what is described as their PostMVP release) for the moment scheduled by the end of the year, I would like to propose the following idea: instead of spending a lot of time and energy to transpile Kotlin to JavaScript, why not targeting directly WebAssembly for your Kotlin frontend effort?

While WebAssembly MVP is similar in term of scope to asm.js and thus more designed for porting C/C++ apps like games for the web, the first standardized version of WebAssembly is likely to support more useful features like setjmp/longjmp or being able to call directly the DOM or Web APIs. The #1 use case mentioned for WebAssembly is “Better execution for languages and toolkits that are currently cross-compiled to the Web (C/C++, GWT, …)”, and that exactly what Kotlin try to achieve.

That said, since native GC support won’t be part of the first versions of WebAssembly, and given the focus on supporting LLVM -> WebAssembly compile chain, WebAsssembly support is probably more related to the upcoming native environment support recently mentioned by Andrey Breslav.

Until now, Javascript was considered as the “bytecode of the web”, but with WebAssembly coming it seems to me that JavaScript will continue to be a target for languages close to JS like TypeScript or CoffeeScript, but for others, transpiling to JS will become a deprecated hack. It is like if you compile Kotlin code to Java in order to run it on the JVM!

I think we have a lot of examples that show the limits of transpiling to JavaScript. As a former Dart Google Developer Expert, I have seen that even with the best developers in that field Google failed to make dart2js a viable option. Transpiling a nice statically typed language with clear semantics to JavaScript leads to a lot of issues and is and will stay a hack. Until now we had no alternative, but now we have one and that’s an opportunity that languages should embrace to really support the Web in the coming years. Rust is a perfect fit for that, but Swift may also be a good candidate for targeting WebAssembly given their LLVM toolchain, but what about languages of the JVM? The lack of CG support make that not straightforward, but possible IMO.

So what could be the advantage for Kotlin to be a pioneer of WebAssembly?

I think that could put Kotlin in the same position than it has in Android world: a better language that produces optimized bytecode for the platform it targets.

Also being able to make concrete feedback to the WebAssembly community group, and maybe make JetBrains part of this community group to be the leader of the JVM ecosystem in that field. WebAssembly is a moving target, so you could be sure that the spec integrate your core needs in the version standardized at the end of the year. That would be a significant advantage for Kotlin frontend support.

Also by supporting WebAssembly, you would also gain JavaScript support for free.

And that could allow you to move faster on the native environment topic by joining forces with “Kotlin frontend” team, since WebAssembly support seems require AOT compilation and maybe LLVM IR generation (since WebAssembly will continue to evolve and since LLVM has first class WebAssembly support, that’s maybe easier to target a well defined format like that).

Instead of being one of the last language to release a JavaScript support, why not being the first language to work on WebAssembly support to build a strong, future proof support for the Web?


#2

If I understand correctly, that would mean that Kotlin offers maximum compatibility on the JVM (Java 6 and up) and minimum compatibility in Javascript (only newest browsers with WebAssembly support).


#3

I think targeting WebAssembly instead of JavaScript will save a lot of time in the long run, since WebAssembly is here to stay. Google, Microsoft, Apple, Mozilla etc. all have interest in it’s existence.

There will be a polyfill that converts WebAssembly to JavaScript. Older browser will therefore be no problem.


#4

Exactly, and I guess the polyfill could be also integrated in Kotlin toolchain in order to generate JavaScript out of the box if the user want that.


#5

tl;dr Yes, we will look at compiling to WebAssembly, but it’s unclear whether we should give up the JS translation we have now or not.

A few points to note:

  • having no GC makes it a considerable challenge to get a a WebAssembly support quickly, thus it’s not really clear how we could give reasonable input to the spec process in so short a time;
  • I haven’t read enough to be sure of it, but if all the existing JS goodies (from jQuery to Angular) are not available in WebAssembly, this would render Kotlin irrelevant for usual front-end work for a considerable time; it’s not a show stopper, but a thing to think about;
  • to make such a back-end useful we’ll need libraries, a lot of them; we (the community) will have to write them all in Kotlin from scratch, there’s no platform to reuse them from; again, not a show stopper, but a thing that changes a lot.

And it looks like in the world of languages newly compiled to WebAssembly competition will be all about libraries, which makes the last point an even bigger thing to think about since JetBrains is not historically a vendor of such libraries as would be needed there.

Also by supporting WebAssembly, you would also gain JavaScript support for free4.

Though formally true, this is not the JS support we’d like (with GC and all the existing libraries), and thus not a valid argument in this discussion.

Bottomline:

  • we are planning to work on an LLVM back-end anyway;
  • compiler-wise WebAssembly doesn’t seem better (or worse) than any LLVM target;
  • API/libraries for it will need some extra attention, and we have to work out a plan for this;
  • contributing to the spec is a reasonable idea, but we need to work out a plan for that too, because our prototype most probably won’t be ready in time.

#6

Also by supporting WebAssembly, you would also gain JavaScript support for free

No, WebAssembly is too low-level, it operates in terms of direct access to memory (and does not even has built-in malloc/free alternatives). When you translate such code back to JavaScript, you get very inefficient bloated code. A better approach would be to implement IR which is quite similar to JVM bytecode (and a little more high-level than WASM), to that it would be easy to lower it to either JVM bytecode, LLVM IR or WASM. And it’s possible to generate JS from this IR. I believe it’s even easier than current AST-to-AST approach, since it causes a lot of problems with inlining and evaluation order.

Also, a few thoughts on performance:

  1. To be compatible with JVM backend, should emulate <clinit> somehow, therefore we have to insert function that calls <clinit> on every access to static field (we can optimize it per-method, but still too many <clinit> invocations to remain). In case of a native environment we can patch generated code and eliminate all <clinit> invocations after it gets actually invoked the first time. WASM does not allow to patch the code.
  2. invokeinterface is a nightmare. Dynamic environments like HotSpot use runtime code generation to implement invokeinterface efficiently. Without it we’ll end up with huge vtables.
  3. Exception handling is a worst thing to implement. In native backend for LLVM people usually generate stack maps and write some native assembly code to unwind stack. Without this we have to insert runtime check after each invocation, which is very slow.
  4. GC is not a big issue, since we can generate shadow stack, but it still would be better to get direct access to stack to increase performance. It’s better to implement moving GC, but we have to patch the stack, which is impossible as well.

#7

I haven’t read enough to be sure of it, but if all the existing JS goodies (from jQuery to Angular) are not available in WebAssembly, this would render Kotlin irrelevant for usual front-end work for a considerable time; it’s not a show stopper, but a thing to think about;

That’s not a big issue. There are two kinds of developers who would use Kotlin on frontend: those who already write server-side logic on Kotlin and want to write some front-end as well and those who came from JavaScript world. Libraries are often important for the latter ones. However, what is the reason for them to drop their favourite ES, TS, CoffeScript and get Kotlin. From my experience with GWT I can say that you usually don’t need these libraries, nor anything from usual JS frontend stack.

Another concern is that we can divide JS libraries into two big sets: libraries and frameworks. Libraries are things like WYSIWYG editors, map viewers, complex table views, etc. They don’t dictate you certain way of writing you code. You write the code as you like and include these libraries. Frameworks like Angular, React, Aurelia do things for you, but force you to organize the code in a certain way. This is usually “JS-way”, which is quite different from statically-typed “Kotlin-way”. So you end up writing JavaScriptish Kotlin code instead of writing on idiomatic Kotlin. There’s no difference for developers of second kind (so why choose Kotlin), and a big pain for delopers of first kind.

WASM is a completely new unoccupied ecosystem that lacks excellent languages like Kotlin. It’s a good chance to occupy it. When we have army of WASM/Kotlin developers who write libraries and fraweworks, it’ll be easier to port these libraries to JavaScript rather than wasting time trying to adopt existing libraries to Kotlin.


#8

Thanks a lot for your feedbacks!

As mentioned by @Alexey.Andreev, I think the main chance for Kotlin to be really successful for frontend development is to push for a real Kotlin frontend ecosystem written idiomatic Kotlin code, and not “JavaScriptish Kotlin” focused on interop with JS ecosystem.

TypeScript has already won the war of statically-typed JavaScript, and I will have hard time to choose Kotlin over TypeScript for my projects with KotlinJS. TypeScript keeps JS semantics and just add what is needed, leading to idiomatic and lightweight JavaScript code, and Kotlin won’t be able to fight at the level IMO. I don’t say JavaScript interop is not important, there is a huge ecosystem and we must be able to reuse it, but that’s not the most important thing to me.

The most important thing to me is to see Kotlin develop its own frontend ecosystem without encouraging people to do “JavaScriptish Kotlin” in order to propose something different than TypeScript, and WebAssembly seems to be the perfect fit to go in that direction.

The fact that JetBrains is not historically a vendor of such libraries is not an issue IMO, I am pretty sure the community will take care of that if you propose something that could attract frontend developers outside current Kotlin community. While I have hard time to see huge adoption coming with the current approach where the only real advantage over TS is to share the code between the server/mobile/frontend applications, building a clean Kotlin ecosystem with proper WebAssembly bytecode generation seems to be something that could attract much more developers. That’s maybe difficult for us to imagine, but a new era is coming where frontend development does not mean necessarily JavaScript.

I guess you know better than me the technical challenge of compiling Kotlin to LLVM/WebAssembly, and that’s maybe a difficult and long road, but the key point to me is that this a road that you guys could significantly influence, that’s a road that a lot of developers would take, and unlike generating JS code, this is not a dead end :wink:


#9

WebAssembly presentation worth to watch.


#10

IMO Kotlin JS is not a dead end :slight_smile: Current Java developer can learn Kotlin easily and use it for backend development. Then rather than learning JavaScript/TypeScript from scratch he might start using some fw/components and do KotlinJS frontend development in almost the same language. Sure some basic understanding of a whole web ecosystem is required as the abstraction is leaking.

The reason why people choose Kotlin over Java are its features like type safe builders or named function arguments. These greatly improves productivity. Why to give up on them during frontend development?

In my team we keep our huge java backend and started rewriting our frontend (VB6, .NET WinForms, WPF, Flex) in KotlinJS. In my team all developers know Java, some .NET but there is no real JavaScript guru. I see no reason for choosing TypeScript over KotlinJS. Well there is one, fear that JetBrains will give up KotlinJS development :frowning:


#11

https://hacks.mozilla.org/2017/02/where-is-webassembly-now-and-whats-next/

On February 28, the four major browsers announced their consensus that the MVP of WebAssembly is complete. This provides a stable initial version that browsers can start shipping.

Adding post-MVP features to the spec

  • Working directly with the DOM
  • Exception handling
  • Garbage collection

#12

If Kotlin doesn’t do it, C# might. And it is looking very promising. Check from minute 28 forward:


#13

Looks highly likely that Kotlin has leapfrogged C#, and created a huge gap. Kotlin Native has a recent sample called html5Canvas (uses WASM) and appears to have some JS interop going on (possible hint of a new kotlinx.wasm project being created in the future?), which is absolutely essential for any language to have significant adoption via WASM. C# is heading down the reinvent the wheel route (creating its own ecosystem), where it is ignoring the JS ecosystem at its peril. Also Microsoft haven’t shown any interest in taking C# to the web frontend area (there are no related official projects).


#14

Kotlin/Native 0.4 introduces experimental WebAssembly support !!!


#15

As it was already stated, Kotlin Native might have good chances to play a major role as compile-to-wasm language in the frontend world.

I am a JavaScript frontend developer. My home is Angular. I am pretty happy with its ecosystem. Anyways, it is far from perfect. I can really well image to use another technology in the future.

And that’s my point - the single page application landscape is still very young but growing rapidly. With WebAssembly coming to the browsers and maturing from experimental status, there are large opportunities for new paths (/technologies) in the frontend world.

I like Kotlin as a language a lot and I would definitely give it a try - also in the frontend.