Crystal in (possible) WASM everywhere future?

It goes a little bit beyond that, but that’s generally the case. I’ve investigated porting Crystal to wasm32-wasi a few times over the last year and been able to get some simple programs compiling and running via various WASM runtimes. I’ve documented some of this here: GitHub - maxfierke/crystal-wasm-tools: Tools for compiling Crystal dependencies, bindings, etc. for use with wasm. I had to disable a lot of features within the stdlib to get anything working, so it’s very very rough, and not super usable for anything particularly exciting

libpcre is relatively easy to port over (documentation contained above), but libgc and libevent2 present difficulties (pthreads are a non-starter until there’s an accepted WebAssembly primitive for threads)

The big blockers are:

  • Fiber support. As @straight-shoota touched on, context switching is impossible to do the way we do for other targets, as WebAssembly does not use registers and doesn’t have anything yet for creating separate stacks. There is a feature in binaryen called asyncify, that could theoretically be used and I started experimenting with but couldn’t get it to work, in order to implement context switching for Fibers. This would make libevent2 somewhat possible for evented I/O, but I had to hack around quite a lot to get libevent2 to even compile for wasm32-wasi, and it basically required taking a hatchet to anything involving networking or socket APIs, since those don’t exist in WASI for the most part
  • Exceptions. Exception handling is not something that exists in WASM yet with WASI, and so there’s no support for C++ exceptions in LLVM and WASM, except for some experimental stuff at the IR layer, but nothing that’s really usable or stable. This means that any exception in Crystal would just crash the program, and trying to avoid exceptions completely is difficult and makes it hard to write anything useful or use much of the stdlib
  • Require ordering weirdness. I found when I started disabling parts of the stdlib, it affected require load ordering and led to a rabbit hole of fixing ordering dependencies in the stdlib, so not sure if there’s a bug there or if it was really something related to the WASM work, but that made it pretty unpleasant as well

It’s possible that targetting wasm32-emscripten, instead of wasm32-wasi, would yield better results, but I didn’t want to have to figure out how to shoehorn emscripten’s custom toolchain wrappers into compiling Crystal and dealing with JavaScript wrappers, etc.

In general, the big blockers really lie at the WebAssembly or LLVM-level, and those proposals move somewhat slowly, so I would caution anyone holding out hope for Crystal on WebAssembly that it will be a while unless the runtimes or toolchains can provide more native capabilities for Crystal to build on

11 Likes