In the past few years, many source-to-source compilers (a.k.a transpilers) have been created to improve JavaScript. Among them, the most well-known are CoffeeScript, Dart, and TypeScript, but the list of such languages is much longer. Transpilers have become such an attractive alternative for programming Web applications, that some proposals such as GPM have raised to standardize the transpilation process in ECMAScript 6. Most transpilers over JavaScript propose a new syntax (CoffeeScript, Dart), or a syntax extension to JavaScript (TypeScript). Some approaches propose to start from an existing language (examples: for Haskell and for OCaml.
JSweet falls in the latter category, starting from the Java language. JSweet is an Open Source Java to JavaScript transpiler that aims at programming modern Web applications (i.e. HTML + JavaScript) in plain Java, using our favorite Java IDEs. There are commonly two typically-given reasons why people would benefit such a transpiler.
However, beyond these obvious reasons, many technical and “business”-oriented choices need to be made in order to build such a transpiler. In particular, the crucial issue to be tackled is the way to access the existing libraries, since it is a fact that, without libraries, a programming language is pointless. So the question that rapidly arises is: which libraries, and how do I get access to them?
In the past, many Java to JavaScript transpilers such as GWT or Java2Script made the choice to transform calls to a Java API (such as SWT for instance) into calls to native JavaScript libraries. This approach has the advantage of seamlessly leveraging the use of JavaScript APIs, so that Java programmers do not need to learn JavaScript at all. When GWT came out, it generated a lot of buzz and hope from the Java community, because most Java programmers do not want to learn JavaScript, but also because such a tool could save a lot of time (and money) when porting legacy Java code to build modern Web applications. As a consequence, people got all exited, because they hoped they could potentially save a lot of money by:
However, real life does not work this way… In practice, there are several flaws to this kind of approaches. Building a transpiler that supports up-to-date Java and JavaScript APIs is extremely difficult and involves a significant delay when compared to projects that directly use the latest APIs natively. The root cause for this is that, in most cases, Java and JavaScript APIs are designed quite differently since the targeted runtime environments (a JRE and a Web Container) differ in many ways. As a consequence, the required in-depth transformations make the system complex to understand and, consequently to debug. In practice, when building more complex applications, it is naive to think that one will not need to understand the details of the generated code, when fine-tuning the Web applications, and trying to use latest state-of-the-art frameworks. Also, it is naive to think that the most complex Java frameworks can be executed in JavaScript. To put it with different words, here are the two main reasons why this approach is not as promising as expected/advertised.
So, why JSweet at all then?
Being agreed that trying to transform Java APIs calls to JavaScript APIs is a too complex task, there is a more realistic approach that consists of completely dropping the Java APIs, and actually using the JavaScript APIs in the Java language. With such an approach, the Java to JavaScript transpiler becomes a syntax mapper between the Java syntax and the JavaScript syntax, all the rest remaining unchanged. Sometimes, I like to call this approach a WYSIWYG transpiler, because what you write will remain unchanged since you directly access the target language APIs, instead of using a source-level API and translating to target ones.
Of course, with such an approach, programmers will not be able to automatically convert most legacy Java code to JavaScript code. For instance, a Swing-based application will never convert to JavaScript, since there is no corresponding Swing API in JavaScript. This limitation is however a good and healthy limitation, because all other in-depth approaches will also hit this limitation sooner or later. Additionally, knowing that Java APIs will not be automatically transpiled, it does not mean that such a transpiler cannot help in manually porting legacy code, or sharing some part of the application between a Java and a JavaScript application. For instance, if the data model (transfer objects or persistent data layer) is written with the Java syntax, and if it does not use too much of the Java APIs, it is possible to share the same code in the Java-written server part, and in the JavaScript-written client part of the same application.
As a consequence, we believe that the syntax mapper (or WYSIWYG) approach is the best solution to bridge Java and JavaScript. Still, it remains the issue of accessing the JavaScript APIs from Java. How do we deal with fast pace releases and the variety of frameworks available in the JavaScript community? For this issue, JSweet proposes the first working solution to translate TSD well-typed libraries from TypeScript, to Java. This API translator currently makes JSweet the only technology to allow the Java programmers to actually take advantage of all JavaScript (not only subsets of it). I will describe this solution in a coming post.