Kiesel Devlog #5: Progress powered by the Shadow web engine
Shadow Web Engine
This is a project my friend CanadaHonk started working on earlier this week — it's a simple web engine written in JS! More about that here.
For JS execution within Shadow they had the idea to use existing Wasm builds of JS engines instead of relying on the host browser, and to my surprise they picked SpiderMonkey and Kiesel for the initial proof of concept, switchable at runtime!
This resulted in me spending an evening fixing bugs and looking into missing features they asked about, including a few of the below. Of course this isn't anywhere near being a serious web engine just yet, but it's really cool to have Kiesel featured in one regardless :^)
I decided to implement classes even before Shadow happened just to make some progress on language features again — they definitely win in the category weirdest codegen across the entire engine, but other than that I'm happy with how that turned out :^)
Supported features include class expressions/declarations, methods (of course),
constructor(), static and instance class fields, static blocks, as well as
super calls and properties (no private properties yet). You can see some of those in action here.
I also added support for parsing async, generator, and async generator method definitions in classes or object literals, but they're just as non-functional at runtime as their function declaration counterparts.
Sharing a screenshot of an entire class being written on a single line with no syntax highlighting prompted CxByte (whom you might know from the SerenityOS project! 👋) to start working on a LibLine Zig port to improve the REPL, more on that soon!
The Beginning of Modules
Don't get too excited just yet, there's not much working here! For now I implemented the distinction between scripts and modules, a flag for the CLI, some basic parsing of import declaration, and the
I had very little to do with the module support in LibJS, so this is new territory for me :^)
Other Language Features
I implemented a couple more small language features:
- Function rest parameters
- Spreading in array and object literals
continuestatements (yes, I went 6+ months without those 😅)
- Optional expressions (
foo?.()) - I remember struggling with this when attempting an implementation in LibJS once, but here it's a very straightforward 140 line diff. Huh!
Resizable Array Buffers
These existed as a proposal for a while and finally got merged into the main spec a couple of weeks ago, so I promptly implemented the new functionality :^)
Reporting of Unhandled Promise Rejections
A small DX improvement; the CLI will now report these two cases at the end of script evaluation:
- A promise was rejected without any handlers
- A handler was added to an already rejected promise
Under the hood this uses the same mechanism as the
rejectionhandled events on the web.
Improved CI Builds
I continue to publish pre-built binaries on files.kiesel.dev, with a few recent changes:
- Use musl for Linux builds
- Strip executable in release modes
- Addition of a Windows aarch64 build (because we can)
- Addition of a Linux riscv64 build (also because we can)
Expand to see the full list of newly implemented builtins 📝
test262 is still steadily going up, now at 35.3%. I check the graph every morning, seeing the small bump from last night's run is very motivating 📈
Collaborating with CanadaHonk so they can use Kiesel in the Shadow web engine has been really fun, and I made lots of progress thanks to that! I'm not sure how quickly modules will take shape from here on, but they create some exciting new abilities such as importable native modules: