93 comments

[ 2.0 ms ] story [ 104 ms ] thread
I easily managed to build quickJS to WebAssembly for running in https://exaequOS.com . So I need to do the same for MicroQuickJS !
It's unfortunate that he uploaded this without notable commit history, it would be interesting to see how long it takes a programmer of his caliber to bring up a project like this.

That said, judging by the license file this was based on QuickJS anyway, making it a moot comparison.

If there were a software engineering hall of fame, I nominate Fabrice.
I wish for this new year we reboot the Web with a super light standard and accompanying ecosystem with

    - A small and efficient JS subset, HTML, CSS
    - A family of very simple browsers that do just that
    - A new Web that adheres to the above
That would make my year.
It needs a good standard library yeah? i don't see that in your list.
Be the change you want to see in the world. If you want to use a specific subset of HTML, CSS and JS, go ahead, make a website using it and offer a browser for similar-spec sites.
On a phone at the moment so I can't try it out, but in regards to this "stricter mode" it says global variables must be declared with var. I can't tell if that means that's just the only way to declare a global or if not declaring var makes it scoped in this mode. Based on not finding anything skimming through the examples, I assume the former?
Clarification added later: One of my key interests at the moment is finding ways to run untrusted code from users (or generated by LLMs) in a robust sandbox from a Python application. MicroQuickJS looked like a very strong contender on that front, so I fired up Claude Code to try that out and build some prototypes.

I had Claude Code for web figure out how to run this in a bunch of different ways this morning - I have working prototypes of calling it as a Python FFI library (via ctypes), as a Python compiled module and compiled to WebAssembly and called from Deno and Node.js and Pyodide and Wasmtime https://github.com/simonw/research/blob/main/mquickjs-sandbo...

PR and prompt I used here: https://github.com/simonw/research/pull/50 - using this pattern: https://simonwillison.net/2025/Nov/6/async-code-research/

Look at how others implement quickjs and restrict its runtime for sensitive workloads [1], should be similar.

But there are other ways, e.g. run the logic isolated within gvisor/firecracker/kata.

[1] github.com/microsoft/CCF under src/js/core

Since you're here and this is likely to become professionally relevant for me pretty soon, what is the best way you know of for securely running Python inside Python?

I was looking for something like Pyodide but runnable from Python, but that doesn't seem to exist quite yet. I can get a Python interpreter to run in wasmtime, but that doesn't have the Pyodide goodies like Micropip etc. Sadly, Pyodide itself seems fully married to JS, as it compiles to Emscripten and not WASI.

I'm almost tempted to just go with a small binary embedding V8 and running Pyodide inside V8 isolates or something.

(I know I can do this via Firecracker / GVisor / whatever, that is not the solution I'm looking for.)

I’m horribly biased but I think it’s a combination of: (1) knee-jerk reaction to similar-looking but low-value comments, and (2) most people not having played around with LLM coding agents and messed around with their own agents enough to immediately jump to excitement at simple, safe sandboxing primitives for that purpose.

And +1000 on linking to your own (or any other well-written) blog.

Curious if you have a specific use case for sandboxed JS that you would share?
I want to build software features where users can configure some additional JavaScript to run in order to customize that software.

One example: given this database table run this JavaScript function against every value in this column to calculate a value to be stored in another column.

Or once a day fetch the JSON from this URL and transform it with this JavaScript and store it here.

I'm not an embedded systems guy (besides using esp32 boards) so this might be a dumb question but does something like this open up the possibility of programming an esp32/arduino board with Javascript, like Micro/Circuit Python?
It's a good _start_; much more code needs to be written to allow control of the hardware of those devices (GPIO, I2C etc).
Timing really is everything for making the frontpage, I posted this last night and it got no traction.
I suspect it's just random luck, not timing.
This engine restricts JS in all of the ways I wished I could restrict the language back when I was working on JSC.

You can’t restrict JS that way on the web because of compatibility. But I totally buy that restricting it this way for embedded systems will result in something that sparks joy

> You can’t restrict JS that way on the web because of compatibility.

Well, now we can run this thing in WASM and get, I imagine, sane runtime errors :)

Fabrice Bellard is widely considered one of the most productive and versatile programmers alive:

- FFmpeg: https://bellard.org

- QEMU: https://bellard.org/qemu/

- JSLinux: https://bellard.org/jslinux/

- TCC: https://bellard.org/tcc/

- QuickJS: https://bellard.org/quickjs/

Legendary.

At this point I'm convinced that they're not a 'real person' and the 'Fabrice' is an operational code name for a very mature hacker collective.

Real people have to sleep at some point!

Wikipedia doesn't list any honours awarded by the French Government. Nor do I see anything from ACM. Definitely overdue some official recognition.
And that’s just his open source work.
When reading through the projects list of JS restrictions for "stricter" mode, I was expecting to see that it would limit many different JS concepts. But in fact none of the things which are impossible in this subset are things I would do in the course of normal programming anyway. I think all of the JS code I've written over the past few years would work out of the box here.
Glad to see a project of Fabrice Bellard on github, finally. I know many great opensource projects exist without public development (notably, sqlite), but is always disappointing to have no public bug tracker, no patch submission, no commit history, contact by email, tarballs (even with a signature, tooling for signed downloads never received any development), etc.
Anyone know how this compares to Espruino? The target memory footprint is in the same range, at least. (I know very little about the embedded js space, I just use shellyplugs and have them programmed to talk to BLE lightswitches using some really basic Espruino Javascript.)
I haven't used Espruino but I spent a while perusing the source code. At least at the time, the implementation strategy was very slow. I lost interest in it in favor of Lua and Micropython.
People talk about how productive Fabrice Bellard is, but I don't think anyone appreciates just how productive he is.

Here's the commit history for this project

b700a4d (2025-12-22T1420) - Creates an empty project with an MIT license

295a36b (2025-12-22T1432) - Implements the JavaScript engine, the C API, the REPL, and all documentation

He went from zero to a complete JS implementation in just 12 minutes!

I couldn't do that even if you gave me twice as much time.

Okay, but seriously, this is super cool, and I continue to be amazed by Fabrice. I honestly do think it would be interesting to do an analysis of a day or week of Fabrice's commits to see if there's something about his approach that others can apply besides just being a hardworking genius.

Love it! Needing only 10K of RAM, it looks like a much better solution to CircuitPython (can squeeze into 32K).
If this had been available in 2010, Redis scripting would have been JavaScript and not Lua. Lua was chosen based on the implementation requirements, not on the language ones... (small, fast, ANSI-C). I appreciate certain ideas in Lua, and people love it, but I was never able to like Lua, because it departs from a more Algol-like syntax and semantics without good reasons, for my taste. This creates friction for newcomers. I love friction when it opens new useful ideas and abstractions that are worth it, if you learn SmallTalk or FORTH and for some time you are lost, it's part of how the languages are different. But I think for Lua this is not true enough: it feels like it departs from what people know without good reasons.
Lua has been a wild success considering it was born in Brazil, and not some high wealth, network-effected country with all its consequent influential muscle (Ruby? Python? C? Rust? Prolog? Pascal? APL? Ocaml? Show me which one broke out that wasn't "born in the G7"). We should celebrate its plucky success which punches waaay above its adoption weight. It didn't blindly lockstep ALGOL citing "adooooption!!", but didn't indulge in revolution either, and so treads a humble path of cooperative independence of thought.

Come to think of it I don't think I can name a single mainstream language other than Lua that wasn't invented in the G7.

It sounds like you're trying to articulate why you don't like Lua, but it seems to just boil down to syntax and semantics unfamiliarity?

I see this argument a lot with Lua. People simply don't like its syntax because we live in a world where C style syntax is more common, and the departure from that seem unnecessary. So going "well actually, in 1992 when Lua was made, C style syntax was more unfamiliar" won't help, because in the current year, C syntax is more familiar.

The first language I learned was Lua, and because of that it seems to have a special place in my heart or something. The reason for this is because in around 2006, the sandbox game "Garry's Mod" was extended with scripting support and chose Lua for seemingly the same reasons as Redis.

The game's author famously didn't like Lua, its unfamiliarity, its syntax, etc. He even modified it to add C style comments and operators. His new sandbox game "s&box" is based on C#, which is the language closest to his heart I think.

The point I'm trying to make is just that Lua is familiar to me and not to you for seemingly no objective reason. Had Garry chosen a different language, I would likely have a different favorite language, and Lua would feel unfamiliar and strange to me.

I also strongly disliked luas syntax at first but now I feel like the meta tables and what not and pcall and all that stuff is kinda worth it. I like everything about Lua except some of the awkward syntax but I find it so much better then JS, but I haven't been a web dev in over a decade
What are the chances of switching to MQJS or something like it in the future?
Lua having a JIT compiler seems like a big difference though. It was a while since that got major updates, but probably relevant at the time?
> If this had been available in 2010, Redis scripting would have been JavaScript and not Lua.

Thank god it wasn’t then.

+1 for the incredibly niche (but otherwise make-it-or-break-it) fact that PUC-Rio is and likely always will be strict C89 (i.e. ANSI C). I think this was (and still is?) most relevant to gamedev on Windows using older versions of MSVC, which has until recently been a few pennies short of a full C99 implementation.

I did once manage to compile Lua 5.4 on a Macintosh SE with 4MB of RAM, and THINK C 5.0 (circa 1991), which was a sick trick. Unfortunately, it took about 30 seconds for the VM to fully initialize, and it couldn't play well with the classic MacOS MMU-less handle-based memory management scheme.

Lua syntax is pretty good for DSL (domain specific language) cases / configuration definitions.

For example Premake[1] uses Lua as it is - without custom syntax parser but with set of domain specific functions.

This is pure Lua:

   workspace "MyWorkspace"
      configurations { "Debug", "Release" }
   
   project "MyProject"
      kind "ConsoleApp"
      language "C++"
      files { "**.h", "**.cpp" }
   
   filter { "configurations:Debug" }
      defines { "DEBUG" }
      symbols "On"
   
   filter { "configurations:Release" }
      defines { "NDEBUG" }
      optimize "On"

In that sense Premake looks significantly better than CMake with its esoteric constructs. Having regular and robust PL to implement those 10% of configuration cases that cannot be defined with "standard" declarations is the way to go, IMO.

[1] https://premake.github.io/docs/What-Is-Premake

I for one would be would be very interested in a Redbean[0] implementation with MicroQuickJS instead of Lua, though I lack the resources to create it myself.

[0] https://redbean.dev/ - the single-file distributable web server built with Cosmopolitan as an αcτµαlly pδrταblε εxεcµταblε

Normally I'd say "it's never too late!" but clearly would diverge and require an entirely new project, maintaining two bases for the same thing, etc.

Good to see you alive and kicking. Happy holidays

> If this had been available in 2010, Redis scripting would have been JavaScript and not Lua.

This would have been a catastrophic loss. Lua is better than javascript in every single way except for ordinal indexing

LuaJIT’s C FFI integration is super useful in a scripting language and I’ve replaced numerous functions previously written in things like Bash with it.

it also helps that it has ridiculously high performance for a scripting language

I wonder when does he have time to do those marvellous things
I find frustrating that imagination of very smart, talented and capable people is captured by JavaScript language, surely they could have done better.
I wonder if this could become the most lightweight way for yt-dlp to solve YouTube Javascript challenges.

https://github.com/yt-dlp/yt-dlp/wiki/EJS

(Note that Bellard's QuickJS is already a supported option.)

That's a great idea, but if they did, then YouTube could retaliate by specifically using features that MicroQuickJS does not support.
There's no reason it has to be lightweight, what it has to do is solve Youtube challenges without workarounds due to limited Javascript syntax.
This guy is incredible. Lzexe, Qemu, TinyCC to name just a few gems.
this would be a killer replacement for micro/circuitpython for embedded devices, assuming there's an elegant TS->MQJS transpile
I don't think you can transpile arbitrary TS in mqjs's JS subset. Maybe you can lint your code in such a way that certain forbidden constructs fail the lint step, but I don't think you can do anything to avoid runtime errors (i.e. writing to an array out of its bonds).
If anyone wants to try out MicroQuickJS in a browser here's a simple playground interface for executing a WebAssembly compiled version of it: https://tools.simonwillison.net/microquickjs

It's a variant of my QuickJS playground here: https://tools.simonwillison.net/quickjs

The QuickJS page loads 2.28 MB (675 KB transferred). The MicroQuickJS one loads 303 KB (120 KB transferred).

Looks like those sizes could be improved significantly, as the builds include names etc. I would suggest linking with

emcc -O3

(and maybe even adding --closure 1 )

edit: actually the QuickJS playground looks already optimized - just the MicroQuickJS one could be improved.

I was interested to try Date.now() since this is mentioned as being the only part of the Date implementation that is supported but was surprised to find it always returns 0 for your microquickjs version - your quickjs variant appears to return the current unix time.
The most important thing about any new JS runtime in 2025, how do I use it from JS? /s
At last, I can run JavaScript in my browser. The world is now complete.