JavaScript Playground
Write plain JavaScript, type its input into the stdin box and press Run: the program runs in a QuickJS engine inside a worker in this browser, not on a server, and the console shows its console.log output, any uncaught error with its line and column, and the value of its last expression. The first run downloads the 503 kB engine from this site and checks it against a pinned SHA-256 hash, and later runs on the page reuse it. Each run gets a fresh engine with a 16 MiB heap and is stopped after 2 seconds of wall-clock time, so a loop that never ends costs two seconds rather than the tab. There is no Node, npm, DOM or network here, and your code is never uploaded.
Press Run, or Ctrl+Enter in the editor. The first run downloads the 503.1 kB QuickJS engine from this site and checks it against a pinned SHA-256 hash.
Ctrl+Enter (Cmd+Enter on a Mac) runs. In the editor Tab indents and Shift+Tab outdents; press Esc, then Tab, to move on from the editor. The program reads the stdin box as the string stdin, or one line per readline() call. main.js and stdin each hold up to 65,536 bytes, and both are kept in this browser until you press Start over.
Examples
Each one loads into the editor with its stdin, and the result beside it is what running it gives.
- sum 108 6 numbers 5
- 5
- ada 9 grace 7 alan 8 total 24
- ink 14.00 pen 5.00 pad 3.50 {"name":"ink","price":7,"qty":2}
- answer 42 Promise { 42 }
- Map(2) { 'ada' => 9, 'alan' => 8 } Set(2) { 'js', 'quickjs' } { user: { name: 'ada', langs: [ 'js', 'c' ], address: { city: 'London' } } } [ 1, [ 2, [ 3, [Array] ] ] ] -0 10n null undefined
- OK Uncaught TypeError: cannot read property 'toUpperCase' of undefined
- undefined undefined undefined Uncaught ReferenceError: 'require' is not defined
- interrupted at 2 s, the page stays responsive
- Uncaught InternalError: out of memory
- stopped at 64 KiB of output
What this engine can and cannot do
QuickJS runs the language itself, and this page adds console, stdin and readline(). These are the edges.
- Modern JavaScript as QuickJS runs it: classes with private fields, async functions, generators, destructuring, BigInt, Map and Set, typed arrays, Proxy, and regular expressions with named groups.
- require, process, Buffer, fs and npm packages do not exist, and an import statement is a SyntaxError: there is no module loader.
- fetch, document, window and every other browser API are undefined, so a program cannot reach the network, this page or your files.
- setTimeout, setInterval and queueMicrotask are undefined. Promises and async functions still work: the jobs they queue run until none is left, within the 2 second limit.
- stdin holds the stdin box as one string. readline() returns the next line on each call, without its line ending, and null once the lines run out.
- await works inside async functions only. Wrap the code in async function main() { ... } and call main() on the last line.
- Intl is undefined, so toLocaleString() is plain: (1234567.891).toLocaleString() gives 1234567.891. Dates use your own time zone.
- Each run gets 2 seconds of wall-clock time, then the engine is interrupted and its worker ended. A try/catch cannot stop that.
- The engine heap is capped at 16 MiB. Past it, an allocation throws InternalError: out of memory, and the console reports it. If small allocations fill it completely, a catch in your own code may receive null instead.
- The stack is 256 KiB, about 1,500 levels of a small recursive function, then InternalError: stack overflow.
- The console holds 64 KiB of output per run. A program that prints more is stopped there, and what came before is kept.
- log, info, debug, warn, error, dir, assert, count, time, group and trace print as Node prints them, format specifiers such as %s and %d included. console.table prints its data the way console.log does, not as a grid.
Engine and licence
The engine is QuickJS by Fabrice Bellard and Charlie Gordon, compiled to WebAssembly by quickjs-emscripten 0.32.0 (Jake Teton-Landis), in its release-sync build from @jitl/quickjs-wasmfile-release-sync. Both are MIT licensed. The engine file is served from this site unmodified and downloads on your first run; the licence file holds both complete notices.
| File | What it is | Size | Licence | SHA-256 |
|---|---|---|---|---|
| quickjs.wasm | QuickJS compiled to WebAssembly (release-sync build), package/dist/emscripten-module.wasm (runtime) | 503.1 kB | MIT | 105c3bed22d457e43e3d1c3c1c6959fda62a8fe06f0fc8a985303c3a2be72232 |
| quickjs-LICENSE.txt | The complete quickjs-emscripten and QuickJS licence notices, package/LICENSE | 2.3 kB | MIT | 446a69ae534aa8612d8b16d3bfc670c5a5050597dca3ce9820441a60d5d04fbb |
Common questions
- Is this a real online JavaScript compiler?
- It runs real JavaScript, but not in the V8 engine that Chrome and Node use. Your code runs in QuickJS, a small ECMAScript engine that compiles each program to bytecode and then interprets it, built here to WebAssembly and running in a worker in your browser. Modern syntax works, including classes with private fields, async functions, generators, BigInt, Map and Set. Because the engine is different, a run time shown here is not a measure of how fast the code would run in Chrome or Node.
- Can I use require, npm packages, fetch or the DOM?
- No. This is plain JavaScript with no Node underneath and no web page around it: require, process, Buffer, fetch, document, window, setTimeout and Intl are not defined, and an import statement is a SyntaxError because there is no module loader. When a program reaches for one of them, the console names it and says what to use instead. For input, use the stdin box.
- How do I read input in this JavaScript compiler?
- Type the input into the stdin box before you press Run. The program sees all of it as the string stdin, and readline() returns the next line on each call, without its line ending, and null once the lines run out. The stdin box holds up to 65,536 bytes, the same limit as the editor.
- Why did my code stop after 2 seconds?
- Every run gets 2 seconds of wall-clock time. At the limit the engine is interrupted and its worker ended, even inside a try/catch, and the console keeps what was printed before it, so an infinite loop cannot freeze the page. Memory has the same kind of limit: the engine heap is capped at 16 MiB, and an allocation past it throws InternalError: out of memory. When many small allocations fill the heap completely, no room is left to build that error, so a catch in your own code may receive null instead. Left uncaught, it is still reported as out of memory.
- Does it support async/await and promises?
- Yes. Async functions and promises run, and the jobs they queue keep running until none is left or the 2 second limit arrives. If the last expression is a promise, the console shows it with its settled value, and a rejected one is reported as an uncaught error with its line and column. There are no timers, so setTimeout does not exist, and top-level await is a SyntaxError: wrap the code in async function main() { ... } and call main() on the last line.
- How does console.log print objects and arrays?
- The way Node prints them: nested objects to two levels deep, up to 100 array items, Map and Set with their sizes, and circular references marked. Format strings such as %s, %d, %i, %f, %j and %O work, console.error and console.warn print in red, and the value of the last expression appears under the output, as a REPL shows it.
Runs plain ECMAScript in QuickJS (quickjs-emscripten 0.32.0) inside a worker in your browser: there is no Node, npm, DOM or network, so fetch, process, require, setTimeout and Intl are not defined. Each run is stopped at 2 seconds of wall-clock time and the engine heap is capped at 16 MiB, so a runaway loop or an oversized allocation ends with a message instead of freezing the page. QuickJS is not the V8 engine in Chrome and Node, so a time shown here is not a benchmark.