Building a JavaScript Runtime using C
(devlogs.xyz)84 points by redbell 6 days ago
84 points by redbell 6 days ago
QuickJS is amazing. You can put in javascript code, run it through QuickJS and make little binary utilities to run on their own.
Someone took QuickJS and put it in wasm so you can run QuickJS in the browser or in node.
https://github.com/justjake/quickjs-emscripten
Fabrice Bellard is on another planet when it comes to programming. He also wrote FFmpeg and QEMU (among other things).
I put QuickJS in https://exaequos.com. You can do graphics app with raylib
> there's no claim being made that this was supposed to be a from-scratch implementation of Javascript
That is exactly how I interpreted the title of the article.
I wrote a JavaScript engine from scratch using C++ back in 2000.
https://www.digitalmars.com/dscript/cppscript.html
I later translated it to D:
https://github.com/DigitalMars/DMDScript/tree/master/engine/...
engines only execute one JS microtask at a time, you must run it in something, that's the runtime.
Duktape is also good for that I hear https://duktape.org/
I guess I would like to see defining your global object in a real use case and adding some functions to your global object that make sense, which admittedly once you ask someone to do the creative work of making a use case that is sensible as they start implementing it they might find it is more useful to complete the implementation of that use case rather than releasing a starter tutorial.
Although not intuitive, it's common to call that the 'runtime' in the JS world, while V8 and JSC would be called 'JS engines'.
Deno used similar wording in a tutorial for creating your own JS runtime using Rust and V8 bindings: https://deno.com/blog/roll-your-own-javascript-runtime
IMO the tutorial is still cool nonetheless, it's a fun subject.
To be fair, all commercial non-browser runtimes (node, bun, deno) are "just" wrappers of V8 or JSC. Some more experimental ones are "just" wrappers of QuickJS and other less known engines.
iiuc its a runtime because the engine just dispatches one javascript microtask and returns to the runtime with a stack of remaining microtasks
How about a formally verified runtime that takes the JS spec & constructs a runtime by converting the spec w/ incremental & verifiable transformations into an executable runtime?
I think you'd need a "proper" formal spec (e.g., JSCert's version of ECMAScript 5 in Coq/Rocq [0]) for that to be feasible. Not exactly sure how "verifiable" would work otherwise.
They also use an unverified parser but good to know this exists.
In general, yes, although it's nice to have more than one javascript implementation. And one advantage of JSC is that it implements tail call optimization (per the ES6 spec).
I wrote my own language that targeted javascript. When I made my language self-hosting, I initially used `bun` (based on JSC), so I wouldn't have to implement a tail call transformation myself. It was expedient.
My goal was to run in a browser, so I did eventually add that transformation and found that my compiler was 40% faster running in node (based on v8).
For those who would like a true "from scratch" implementation of JavaScript, Fabrice Bellard's QuickJS [1] is clean, readable and approachable. It's a full implementation of modern JavaScript in a straightforward project, not nearly as complex or difficult as V8.
[1] https://bellard.org/quickjs/