QuickJS-NG 0.9.0 released!

QuickJS is a small and embeddable JavaScript engine. It aims to support the latest ECMAScript specification. QuickJS NG is a fork of the original QuickJS project by Fabrice Bellard and Charlie Gordon, after it went dormant, with the intent of reigniting its development.

After a couple of months of development version 0.9.0 is out. A few notable changes:

  • qjs will now exit on unhandled rejections: this aligns the reference interpreter with Node, Deno and Bun
  • Tons of new C APIs: JS_IsDate, JS_IsRegExp, JS_IsMap, JS_IsPromise and more, check quickjs.h
  • QUICKJS_NG is now defined so applications wanting to support both the old version and NG have an easy way to tell them appart
  • Inline caches have been removed, see the interesting conversation here
  • Amalgamated builds, see quickjs-amalgam.zip in the release artifacts, just a C file and 2 header files!
  • Meson build system support

See the full changelog here.

TIL: the default stack size on Windows is 1MB

When compiling with MSVC. Here is how I learned that.

We are close to merging Meson support for QuickJS. During the PR review a test was failing when compiled with Clang and ubsan in debug mode. It turned out to be related to the test setting a very small stack size for the interpreter, so I suggested to remove it entirely. Tests passed! … except on Windows. They now failed on all configurations, not only in debug mode. Time to dig in.

The first step is of course try and reproduce the problem. Luckily I have an old Windows laptop where I can test stuff. I could easily reproduce the problem. The api-test target consistently failed. It simply crashed without providing any output. Checking the exit code ($LASTEXITCODE on PowerShell) yielded -1073741571.

So, since it’s 2025 I decided to ask ChatGPT and see if it could shed any light, and it was right on the money:

The exit code -1073741571 (or 0xC00000FD in hexadecimal) indicates a Stack Overflow Exception (STATUS_STACK_OVERFLOW).

Aha! I had recently updated the default interpreter stack size to 1MB, so I wondered if the default stack size on Windows would be around that value, and thus it would crash before it could be caught by the engine. Guess what, it’s exactly 1MB. Bingo! (While writing this post I ran into the conversation Ben and I had about the V8 default in that very PR, which did mention the 1MB!)

Turns out it’s also easy to set it at build time: passing the /STACKSIZE linker flag. Adding /STACK:8388608 to the linker would set it to 8MB, as the default is on Linux. I created a PR setting it to 8MB both for MSVC and MinGW (for consistency) and the tests were green, success!