kassany/dunjs

By kassany

Updated about 2 months ago

Agnostic JavaScript & TypeScript runtime to swap engines — QuickJS (default), JavaScriptCore, V8

Image
Languages & frameworks
Developer tools
0

2.0K

kassany/dunjs repository overview

DunJS

Pick your JS engine. Ship secure code. Zero compromises.

v1.x · Written in D · QuickJS · JavaScriptCore · V8

One image. Three battle-tested JS engines. A permission model that says no by default. Run JavaScript and TypeScript the same way you'd run any trusted CLI tool — explicit, auditable, fast.


30-second start

# JavaScript
docker run --rm -v "$PWD":/app -w /app kassany/dunjs run server.js

# TypeScript
docker run --rm -v "$PWD":/app -w /app kassany/dunjs run app.ts

Need more power? Swap the engine with one env var:

-e DUN_BACKEND=jsc   # JavaScriptCore — 0.99× Bun throughput
-e DUN_BACKEND=v8    # V8             — matches Node.js startup
                     # default: QuickJS — 9.8 MB binary, interpreter-fast

Secure by design

Every I/O operation is blocked until you say otherwise. No silent network calls. No surprise file reads. Just what you permit, nothing more.

# Read-only access to one directory
docker run --rm -v "$PWD":/app -w /app kassany/dunjs run --allow-read=./data app.js

# Network + read for a real server
docker run --rm -v "$PWD":/app -w /app kassany/dunjs run --allow-net --allow-read server.js

# Full trust — your call
docker run --rm -v "$PWD":/app -w /app kassany/dunjs run --allow-all app.js

Scoped to paths and hosts: --allow-read=./data, --allow-net=api.example.com


What you get

Runtimes you already know, APIs you already use:

// Node.js style
const fs   = require('fs')
const http = require('http')
const { Buffer } = require('buffer')

// Deno style
await Deno.readTextFile('./config.json')
await Deno.serve({ port: 3000 }, handler)

// Web platform
const res = await fetch('https://api.example.com/data')
const hash = await crypto.subtle.digest('SHA-256', data)

Built-in batteries:

WhatHow
TypeScriptStrip-transpiled on the fly — .ts, .tsx, no install
npm packagesdun install lodash + CVE audit via OSV.dev
HTTP/2HPACK, ALPN/TLS, stream multiplexing
HTTP/3QUIC via lsquic — dun:http3
SQLiteVendored, zero external deps — dun:sqlite
WorkersSharedArrayBuffer + Atomics on all 3 engines
30+ Node modulesfs, path, crypto, events, stream, zlib, dns, ws, child_process, …
30+ Deno APIsDeno.env, Deno.stat, Deno.serve, Deno.permissions, …

CLI

  run <file>       Run a JavaScript/TypeScript file
  test [files]     Run tests (*.test.{js,ts}, *_test.{js,ts})
  bench [files]    Run benchmarks (*.bench.{js,ts})
  repl             Start interactive REPL
  eval <code>      Evaluate JavaScript code
  install <pkg>    Install npm package to node_modules/
  audit            Scan node_modules/ for known CVEs
  init [name]      Initialize a new project
  fmt [files]      Format JavaScript/TypeScript files
  bundle <entry>   Bundle JS/TS modules (--outdir DIR)
  clean            Remove cache and build artifacts
  version          Print version
  help             Show this help

Numbers

Throughputfeature_bench (25 tests, release build):

ops/sec
Bun 1.3491 Mbaseline
DunJS JSC488 M0.99× Bun
Node 22172 M0.35×
DunJS V8160 M0.33×
DunJS QuickJS22 Minterpreter — no JIT

Cold start (process spawn, eval ';'):

Bun11 ms
DunJS V822 ms
DunJS QJS / JSC27 ms
Node 2227 ms
Deno 2.742 ms

HTTP throughput (V8, /plaintext): 62,900 req/s — +41% over Node.js v22

Binary sizes (stripped, release):

DunJS QuickJS9.8 MB
DunJS V856 MB
DunJS JSC60 MB
Bun89 MB
Node.js / Deno119 MB

Production-ready image

The Dockerfile pass CIS Docker Benchmark §4 out of the box:

  • Digest-pinned base — debian:bookworm-slim@sha256:…, no floating tags
  • tini as PID 1 — proper SIGCHLD, no zombie workers
  • Non-root USER 1001:1001 — Kubernetes runAsNonRoot compliant
  • SUID/SGID bits stripped from the runtime layer
  • Toolchain verified with sha256sum -c at build time
  • HEALTHCHECK runs dun eval "1+1" on every start
  • Full OCI label set + STOPSIGNAL SIGTERM for graceful shutdown

Harden further at runtime (CIS §5):

docker run --read-only --tmpfs /tmp \
  --cap-drop=ALL --security-opt no-new-privileges:true \
  --pids-limit 256 --memory=512m \
  kassany/dunjs run script.js

Tag summary

Content type

Image

Digest

sha256:c8516c70d

Size

134.6 MB

Last updated

about 2 months ago

docker pull kassany/dunjs