BuckleScript 4.0.8 (Part One)
Today we released version 4.0.8 of bs-platform
. A detailed list of changes is available here.
Most user-facing changes are bug fixes and small enhancements, while quite a lot of work has been done behind the scenes towards the more fundamental improvements coming down the line. This blog post refers to the BuckleScript runtime and some of the work we are doing to improve it.
The design goal of BuckleScript is to make the runtime as small as possible. This runtime is divided into two parts: the C shims, and the fundamental language feature support.
The C shims are not a strict runtime requirement: in the native backend, the functions are implemented in C, but in BuckleScript this isn't necessary. We can either implement the C shims in a polyfill style or we can just implement them in OCaml and compile via BuckleScript. Recently, we have been shifting more and more work from the runtime to the normal OCaml stdlib by patching it with conditional compilation. The benefit is obvious – they are just normal functions which do not need special compiler support – but the downside is that we might need to make more patches to the libraries which use C functions, but considering the more challenging part of maintaining the patches to the compiler, we think such overhead is worthwhile.
If we ignore the C shims, the BuckleScript runtime is very small, and it is pretty easy for experienced BuckleScript programmers to write runtime-free code which generates standalone JS code. Such code could include supporting curried calling conventions, encoding of OCaml ADT, etc.
The BuckleScript runtime is written in BuckleScript itself. The benefit of this is that it is much more maintainable than implementing in JS itself, and it is easier to keep some invariants when crossing the boundary between the runtime and the stdlib. For example, we don't need to worry about the consistency of the runtime encoding of type tuple
in BuckleScript, since the runtime is also implemented in BuckleScript itself, and we get three output modules for free thanks to this "dogfooding".
However, this makes the build system pretty complicated and fragile, and the dependencies between each module are mostly hard coded. Even worse, this introduces a hard dependency between the normal libraries and the runtime binary artifacts.
In particular, one issue we want to address is to make the BuckleScript toolchain lightweight. We will continue to implement the BuckleScript runtime by using BuckleScript itself, but we want to get rid of dependencies like the support for exceptions. In the end, installation will no longer involve building the runtime: BuckleScript will simply be a bunch of generated JS files, so the complexity of the build system will not impact users at all. This is quite important given that we are committed to supporting Windows.
In the future, we will therefore be able to distribute the runtime as a normal JS library, and the BuckleScript user will only need the binary compiler and a small set of JS files. They will be able to use stdlib, Belt or anything else.
To get rid of such dependencies between stdlib and the runtime, we are going to introduce a breaking change in the future. In hindsight, our support for catching JS exceptions exposed the concrete representation of the exception encoding, in particular:
match ... with
| OCamlException exn -> ..
| Js.Exn.Error e -> ...
In this release, we introduced a function to avoid exposing such exception constructors:
match ... with
| OCamlException exn -> ...
| e ->
match Js.asJsExn e with
| Some jserror -> ..
| None -> ...
We encourage you to make such changes yourself to future-proof your codebases.
Oh and by the way, one side effect of this refactoring of the BuckleScript runtime is that the compilation does not require reading of the generated .cm*
files, which means faster compilation :)