JS

runtime.js

One spine: the evolution of JavaScript

Pick an era, expand a concept, and see where it lands in today's runtimes. Every snippet can be dropped straight into the sandboxed console — the event loop panel then shows real, instrumented execution, not a looping animation.

Modern JS

ES2020+2020 – today

Yearly, incremental releases. Small operators that erase enormous amounts of defensive boilerplate, plus top-level await for module-scope asynchrony.

A module can await at its top level. Importers of that module wait for it — the module graph itself becomes asynchronous.

const started = Date.now();
await new Promise((resolve) => setTimeout(resolve, 50));
console.log("module body resumed after", Date.now() - started, "ms");
console.log("importers of this module waited for it");
Top-level await support
V8Implemented at the engine level since V8 8.9; requires the host to use the async module evaluation API.
// engine feature since 8.9 — the host must opt in
// to the async module evaluation API
Node.jsWorks in `.mjs` / `"type": "module"` files. Unavailable in CommonJS — a common migration blocker.
// main.mjs — ESM only; throws in CommonJS
const data = await fetch("https://example.com/api");
DenoAvailable everywhere, including the REPL, since all modules are ESM by default.
// works in every module and the REPL
const data = await fetch("https://example.com/api");
BunSupported in both ESM and its CommonJS interop layer, which transparently wraps CJS files.
// ESM and the CJS interop layer both support it
const data = await fetch("https://example.com/api");

Interview gotchas

15 genuinely tricky, well-known snippets — event-loop ordering, closures in loops, and `this`-binding traps. Open one, read the gotcha, then drop it straight into the sandboxed console to watch it really run.

Event loop
Closures & scope
this binding
Promises & async
Coercion & equality
Built-in traps