Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: I built a WASI playground for running CLI binaries in the browser (runno.dev)
115 points by benno128 on Oct 10, 2022 | hide | past | favorite | 24 comments



G'day! It's a bit hard to understand what this is, because there's a lot of other stuff in the space. What I've written here is a WASI runner for the browser. I've also hooked up a terminal and virtual FS to it. WASI (WebAssembly System Interface) is a standard aimed at writing portable WebAssembly binaries that can run on servers, embedded devices, or locally on your computer. It's not really aimed at the browser. I went through and implemented the whole standard in TypeScript - then built this interface around that implementation so I could play with it.

One really neat thing here is how easy it is to write Rust that targets WASI. If you're into Rust, I'd recommend looking at the source of the demos and then trying out your own WASI binaries.

Here to answer questions if anyone has any!


UPDATE: I found it; here's the very nice core of his new WASI implementation -- https://github.com/taybenlor/runno/blob/main/packages/wasi-m...

Original comment below:

> " I went through and implemented the whole standard in TypeScript"

Isn't this file in your code a big part of the implementing the WASI standard?

[1] https://github.com/taybenlor/runno/blob/main/packages/wasi/s...

I ask because you didn't write that. I was excited that you said " I went through and implemented the whole standard in TypeScript" since I have been working on that same code [1] as the core of this npm package https://www.npmjs.com/package/wasi-js and I've found some subtle bugs in it. I was excited to find another implementation to compare, so maybe you also did something else? Thanks!

This is a very exciting space and I greatly appreciate your work.


Good spotto! That's an old WASI runtime from wasmerjs (https://github.com/wasmerio/wasmer-js).

That's not the WASI runtime being used in this playground. The one in this playground is @runno/wasi-motor (https://github.com/taybenlor/runno/tree/main/packages/wasi-m...). I haven't released it as an NPM package, but it's all MIT so feel free to copy it.


Score another point for memfs, the in-memory node.js fe impl (which if Im reading this right underpins your wasi fs impl). https://github.com/streamich/memfs

Edit: apologies... your reply says you have you own impl! Damn, awesome! Apologies, I'd seen memfs in a dependencies here: https://github.com/taybenlor/runno/blob/main/packages/runtim...

WHATWG recently took up File System Access spec as their FS spec. It both looks semi promising, but they seem to only care about & are only building specs for specifically emscripten wasm users. Only sync apis, only usable from dedicated workers... there's some hopes for more latter but feels super weird to see the web finally get fs access & have it be fast... but for it to be extremely odd shaped hand tailored to a very narrow class of use.

https://fs.spec.whatwg.org/


memfs is very cool, but the WASI runner in this demo doesn't use it. I implemented my own virtual filesystem (see: https://github.com/taybenlor/runno/blob/main/packages/wasi-m...).

Will look at the FS spec. I would hope that it would be shaped in a way that makes sense for WASI (brief look seems like it is). I'd also love it to be something that makes sense from the JavaScript side as well.


I've also put up an article with a walkthrough of how to use the playground to run FFmpeg: https://runno.dev/articles/ffmpeg


Do you think you could make ffmpeg one of the demos like you did with quickjs?


Good idea! It's a bit harder, but totally doable.


There is the .wit in "component model" proposal that is actively developing. Could you explain how it's going to make different between your work here without the .wit and with the .wit files?


I don't really know much about the component model, sorry!


Very cool. This is super relevant to me, I've been porting Trealla Prolog to WASI recently[1] and I've been considering moving from wasmer-js to libapps/wasi-js-bindings. This looks like a nice alternative as well.

I tried running Trealla (you can grab a binary from here https://wapm.io/guregu/trealla) and it seems to work but it doesn't echo any of my input text. Does this have the terminal in raw mode by default? I'm curious how this works given that WASI lacks termios.h.

I always thought a "Steam for text games/CLI apps" would be super cool (ala webassembly.sh) but the WASI spec is missing a lot of terminal-related things: https://github.com/WebAssembly/WASI/issues/161

[1]: https://github.com/guregu/trealla-js


Oh awesome!! I've just added Trealla to my issues list to add it to Runno.

If you go into settings you can switch stdin echo on/off. I have stdio devices set up to return their file type as "Character Device" (see: https://github.com/taybenlor/runno/blob/main/packages/wasi-m...). It seems like some binaries handle this well and act like they are directly connected to the TTY (e.g. my quickjs example). Not sure how they determine that. I'm very much coming at this from a web-developer interested in WASI direction, and not from any experience with OSes or linux.

Edit: btw my WASI runtime (@runno/wasi-motor) is very much in "I haven't even released it as an NPM package" state but you're welcome to copy the code and use it https://github.com/taybenlor/runno/tree/main/packages/wasi-m...


Thanks! This project is super cool. Looks like it is well on its way to replace the broken polyfill at https://wasi.dev.

That makes sense about the stdio file type. I will play around with it and see what I can do. I think I need to copy whatever QuickJS is doing :)

I'll keep an eye on your WASI runtime. I was just about to start hacking on the same thing. Dropped a comment in your issue about Trealla as well. Let's make WASI in the browser awesome!


webassembly.sh is the prior art in this area. It has a package manager that will install binaries automatically. It seems like a poor terminal implementation however, since it uses prompt() for user input. If you rehost it setting the headers described here [1] then the problem is fixed

[1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...


Yeah absolutely. Webassembly.sh was a big inspiration for my original build for Runno (https://runno.dev). The `prompt` issue is caused by code-rot, it used to work but then stopped working after browsers standardised a workaround for Spectre vulnerabilities in `SharedArrayBuffer`. Runno uses some neat tricks to get around this even when `SharedArrayBuffer` isn't available.

Part of the reason I started working on this playground was because I felt like the Wasmer WASI runner didn't work in the ways I wanted it to. Having a full end-to-end understanding of my WASI implementation has really helped, and I'm looking forward to moving Runno over to my new WASI runtime.


Thanks for sharing! I ended going down a WASI rabbit hole ending with my mind being blown realizing an Arduino could run Wasm/WASI.

A binary that can run in browsers, CLI, server, serverless, and even micro controllers!


Which wasi runtime targets avr? Wasm micro still seems to need an os and only targets x86 arm, and riscv.


It’s really cool stuff, hey! Early days but really interesting applications in serverless so far.


I'm confused. Searching for WASI leads me here

https://github.com/WebAssembly/WASI

Which has no links to any readable docs or specs.

¯\_(ツ)_/¯


Yeah the documentation is rather lacking and hard to understand. The best place to start is here: https://wasi.dev/


Looks great, but you lose marks for missing the chance to call it WASI-modo.


I laughed hard at this one! haha


wow, this is cool! the quickjs running with syntax highlighting working really caught my eye.


Thanks!

What's super neat here is that I didn't have to build that. The WASI standard defines `fd_fdstat_get` which tells the binary the type of the file descriptor. For stdin/stdout/stderr I return that it is a "Character Device" (https://github.com/taybenlor/runno/blob/main/packages/wasi-m...). QuickJS understands that means it's running in a TTY and so it emits all the right characters to do colouring. XTerm.JS then interprets those characters and displays the appropriate colours.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: