Status: BETA. The core engine is stable and the standard library surface is complete; pre-1.0 releases may change names, options and defaults. Production use is at your own judgement; pin a version (
install.sh --ref <tag>).
DynaJS is an embeddable, high-performance JavaScript engine and runtime: a from-scratch JS engine (ES2023-class surface) with a built-in native standard library (dyna:*), multi-architecture SIMD acceleration, HTTP/TLS networking, data science tooling, and a single static, dependency-free binary for macOS, Linux and FreeBSD.
Everything ships in one binary. There is no node_modules, no runtime dependency, and no package registry — modules are compiled in or linked from the system's security-tracked libraries (OpenSSL, SQLite, zstd, brotli).
Engineering highlights:
./dev.sh gate).Array, String and Number gain the data-wrangling surface that otherwise requires a utility dependency: grouping, keyed sorting, deduplication, sampling, transposition, string case conversion, template formatting, byte-level transforms and human-readable formatting. Implemented as compiled C — no interpreter step per element — with string scanning, counting, matching and RegExp fast paths dispatched through the same runtime-selected SIMD kernels as dyna:simd.fetch/Request/Response/Headers/FormData, WebSockets, an HTTP server with strict JSON-RPC 2.0 endpoints (batched, promise-aware) and an L4 TCP proxy — all driven by the native event reactor on kqueue (macOS/BSD) and epoll (Linux), whose backend fd folds into an outer event loop.dyna:ml ships classifiers, regressors, clustering, decomposition and scalers — decision trees, random forests, k-NN, K-means, DBSCAN, linear/logistic regression, SVMs, gradient boosting, PCA — fitted in C over contiguous doubles, with persistence built in: every fitted model round-trips through serialize()/deserialize() to bit-identical predictions. Train and serve in one process, no Python bridge.simd.active(), so a deployment can audit which code path it runs..env, YAML, JSON5, CSV and XML for configuration and text.libdynajs.a; dynajsc compiles JavaScript to bytecode embedded in a single native executable, with the engine statically linked in — the target needs no JS source and no separate runtime to install.-e one-liner with top-level await, the HTTP server is syscall-bound, and heavy loops run through the SIMD kernels — timings do not depend on optimization history.serialize()/deserialize(), so state moves across a process boundary as bytes.RRule), civil calendar types (PlainDate, PlainDateTime), durations and time zones.One command on macOS, Linux or FreeBSD:
curl -fsSL https://raw.githubusercontent.com/corporatepiyush/dynajs/master/install.sh | bash
The installer clones the source into ~/.cache/dynajs-build, builds from scratch with the full native standard library, and installs one static binary to /usr/local/bin/dynajs (falling back to $HOME/.local/bin when that needs root and sudo is unavailable). It asks no questions, so it is safe to pipe. Re-running it is how you upgrade: it pulls the latest source, rebuilds, and overwrites the old binary. The full build log is kept at ~/.cache/dynajs-build/install.log.
Options:
install.sh --prefix "$HOME/.local" # install to a different prefix
install.sh --ref v1.2.3 # pin a tag instead of master
install.sh --with-deps # also install missing build tools (brew/apt/dnf/...)
install.sh --dry-run # print the plan and preflight report, install nothing
install.sh --uninstall # remove the installed binary
install.sh --verbose # stream the build output
A first install needs git, make and a C compiler (clang preferred). On macOS the Xcode Command Line Tools provide all three. The preflight report says exactly what is missing before anything is downloaded.
// hello.js
import { zstd, unzstd } from "dyna:compress";
const data = new Uint8Array(Array.from({ length: 1000 }, (_, i) => i % 7));
console.log("round trip ok:", unzstd(zstd(data)).every((v, i) => v === data[i]));
dynajs hello.js # run a file
dynajs -e 'print(1 + 1)' # evaluate an expression
dynajs -i # REPL with history, tab-completion and \h help
// Standard WHATWG globals work out of the box
const res = new Response(JSON.stringify({ hello: "world" }), {
status: 200,
headers: { "Content-Type": "application/json" }
});
console.log("Response ok:", res.ok);
res.json().then(data => {
console.log("JSON:", JSON.stringify(data));
});
usage: dynajs [options] [file [args]]
-h --help list options
-e --eval EXPR evaluate EXPR
-i --interactive go to interactive mode
-m --module load as ES6 module (default=autodetect)
--script load as ES6 script (default=autodetect)
--strict force strict mode
-I --include file include an additional file
--std make 'std' and 'os' available to the loaded script
-T --trace trace memory allocation
-d --dump dump the memory usage stats
--no-unhandled-rejection ignore unhandled promise rejections
-s strip all the debug info
--strip-source strip the source code
--io-threads N IO worker threads (default max(ncpu,4); 0 runs
every offload inline, the no-pool control)
-q --quit just instantiate the interpreter and quit
Top-level await works in -e and in scripts, so dynajs -e 'import("dyna:uuid").then(u => print(u.v7()))' is a valid one-liner.
Every module is documented function-by-function in the API reference.
| Module | What it provides |
|---|---|
dyna:bytes | Work with raw binary data: build, slice and search byte buffers, fixed-width reads/writes, hex/base64 views, and UTF-8-safe Text strings |
dyna:cli | Build friendly command-line tools: argument parsing, ANSI-styled output, prompts, progress bars, spinners |
dyna:compress | Squeeze data and pack archives: zstd, brotli, snappy, gzip, LZ4, tar, zip — decompression caps refuse bombs instead of running out of memory |
dyna:config | Read configuration files: TOML 1.0, INI, .env, front matter |
dyna:crypto | Anything secret-dependent: AEAD encryption (AES-GCM, ChaCha20-Poly1305), signatures (RSA, ECDSA, Ed25519), key exchange, password hashing (Argon2id, scrypt, bcrypt), X.509 certificates, JWT |
dyna:csv | Read and write CSV (RFC 4180): streaming, type inference, and a file-backed table |
dyna:dataframe | Columnar data in plain JS: filter, sort, group-by, join, window functions and quantiles over TypedArrays |
dyna:decimal | Exact decimal and money arithmetic (IEEE decimal128, 34 significant digits) — no binary-float rounding surprises |
dyna:encoding | Format everything: charset detection, base64/base32/hex and friends, varints, JSON5, JSONPath, QR codes |
dyna:file | Filesystem work: atomic writes, file locks, watchers, globs, temp files, platform directories |
dyna:hash | Digest data: SHA-1/2, SHA-3, BLAKE2/3, CRC32 (hardware-accelerated), xxHash, fingerprints — one-shot or streaming |
dyna:html | Web content, server-side: an HTML5 tokenizer, CSS-selector queries, a sanitizer, markdown rendering, templating — every context escapes through one audited escaper |
dyna:http | The web platform: WHATWG fetch/Request/Response/Headers/FormData, an HTTP server in a few lines, WebSockets, multipart and header codecs |
dyna:json | Edit JSON documents: JSON Pointer (RFC 6901) lookups, JSON Patch (RFC 6902) with copy-on-write |
dyna:log | Structured logging: one JSON object per line, leveled, grep- and pipe-friendly |
dyna:matcher | Search text fast: Levenshtein edit distance, tries, Bloom filters, Aho-Corasick multi-pattern search, diffs |
dyna:mathx | The math toolbox: statistics, combinatorics, big integers, number theory, linear algebra, interpolation, special functions |
dyna:ml | Train models in-process: trees, forests, k-NN, K-means, DBSCAN, linear/logistic regression, SVMs, gradient boosting, PCA, scalers — C over contiguous doubles |
dyna:net | Everything under HTTP: IP/CIDR arithmetic, TCP/UDP sockets, a DNS client and server, Redis/PostgreSQL/SQLite clients, rate limiting, metrics, an L4 proxy (statically import this or dyna:http, not both) |
dyna:random | Randomness done right: OS-entropy floats, ints, bytes, shuffles, choices — plus a seedable PRNG for reproducible runs |
dyna:schema | Validate data against JSON Schema (Draft 2020-12); schemas compile once, validation is pure dispatch |
dyna:scrape | Crawl politely: robots.txt with token matching, per-host pacing, jittered retries, conditional GETs, RFC 3986 redirect resolution, response caps — the politeness layer that keeps you off blocklists |
dyna:semver | Version numbers done right: semver 2.0.0 parsing, ranges, comparison, incrementing |
dyna:serialize | Binary interchange: protobuf wire codec, ASN.1 DER, MessagePack, CBOR, BSON — for talking to anything that isn't JSON |
dyna:simd | Explicit vector math: reductions, dot products, distances, matrix ops — the fastest kernel your CPU supports, picked at startup |
dyna:structures | The data structures JS never shipped: LRU caches, graphs (Dijkstra, A*, MST, BFS/DFS), heaps, segment trees, disjoint sets, tries |
dyna:sys | Talk to the OS: subprocesses, environment, arguments, CPU/memory facts, terminal formatting |
dyna:time | Dates that work: RFC 5545 recurring events (RRule), Duration, civil calendar types (PlainDate, PlainDateTime), time zones, formatting |
dyna:uring | Linux-only blistering disk I/O: io_uring batches many block reads into one submit/complete cycle per batch (built with CONFIG_IO_URING) |
dyna:url | URLs and domains: WHATWG URL parsing, IDNA 2008/UTS #46, Punycode, form encoding |
dyna:oauth2 | OAuth 2.0 helpers (optional): PKCE S256, state CSRF, bearer auth, WWW-Authenticate, scope & redirect_uri checks — no IO, no JWT dep for HS* |
dyna:uuid | Identifiers: UUID v1–v7 from the OS CSPRNG, plus NanoID and ULID |
dyna:validate | One-line checks: is this an email, a URL, a UUID, a credit card, a semver, an IP? Each a boolean predicate |
dyna:xml | XML parsing — streaming SAX, a tree, or a plain object with XPath-lite access — with sane size caps on by default |
dyna:yaml | YAML 1.2 parsing; anchors and aliases are refused by name, never silently dropped |
Core engine extensions (also in the API reference): Array, String, Number, Object, Date, RegExp extras.
Each of these blocks is executed by the project's own documentation gate, so they are known to run against the current binary.
import { fetch, Request, Response, Headers, AbortController, FormData } from "dyna:http";
// Global fetch is also available on globalThis
const response = await fetch("https://api.example.com/data", {
method: "GET",
headers: { "Accept": "application/json" },
timeout: 5000
});
const data = await response.json();
A real server in a few lines:
import { HTTPServer } from "dyna:http";
const server = new HTTPServer({ port: 8765 });
server.on("request", (req, res) => {
res.json({ route: req.url, method: req.method });
});
server.listen();
// curl http://localhost:8765/hello
import { Bcrypt } from "dyna:crypto";
// Password hashing (shipped in every build)
const hash = Bcrypt.hash("my_secure_password", 10);
const valid = Bcrypt.verify("my_secure_password", hash);
console.log("Bcrypt valid:", valid);
RSA/ECDSA/X.509 exist only in CONFIG_TLS=y builds:
import { RSA, X509 } from "dyna:crypto";
// Key generation and self-signed X.509 certificate
const keypair = RSA.generate(2048);
const certPem = X509.generateSelfSigned({
key: keypair.privateKey,
subject: "localhost",
days: 365
});
const parsed = X509.parse(certPem);
console.log("Cert subject:", parsed.subject);
console.log("Cert serial:", parsed.serialNumber);
import { Schema } from "dyna:schema";
import { Pointer, Patch } from "dyna:json";
// JSON Schema validation (2020-12)
const schema = {
type: "object",
properties: {
id: { type: "integer", minimum: 1 },
name: { type: "string" }
},
required: ["id", "name"]
};
const result = Schema.validate(schema, { id: 10, name: "Alice" });
console.log("Schema valid:", result.valid);
// JSON Pointer (RFC 6901) & Patch (RFC 6902)
const doc = { users: [{ name: "Alice" }, { name: "Bob" }] };
console.log("Pointer read:", Pointer.get(doc, "/users/1/name"));
const patched = Patch.apply(doc, [
{ op: "replace", path: "/users/1/name", value: "Charlie" }
]);
console.log("Patched:", JSON.stringify(patched));
import { TOML } from "dyna:config";
const tomlText = `
title = "DynaJS Config"
[owner]
name = "Admin"
ports = [ 8000, 8001, 8002 ]
`;
const config = TOML.parse(tomlText);
console.log("Config title:", config.title);
console.log("Owner name:", config.owner.name);
const formatted = TOML.stringify(config);
console.log("TOML output length:", formatted.length);
import { URL, domainToASCII, domainToUnicode, punycodeEncode } from "dyna:url";
const url = new URL("https://bücher.example.de/path?q=1#hash");
console.log("Host:", url.host);
console.log("Punycode ASCII:", domainToASCII("bücher.de"));
console.log("Unicode Domain:", domainToUnicode("xn--bcher-kva.de"));
import { RRule } from "dyna:time";
// Weekly meeting every Tuesday for 4 occurrences
const rule = new RRule({
freq: "WEEKLY",
byday: ["TU"],
count: 4,
dtstart: new Date(2026, 7, 18, 10, 0, 0)
});
const dates = rule.all();
console.log("Recurrence count:", dates.length);
import { DataFrame } from "dyna:dataframe";
const df = new DataFrame({
id: new Int32Array([1, 2, 3, 4]),
score: new Float64Array([95.5, 82.0, 88.5, 77.0])
});
console.log("mean:", df.MEAN("score"));
console.log("top scores:", Array.from(df.N_LARGEST("score", 2)));
import { DecisionTreeClassifier } from "dyna:ml";
const X = [[1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0]];
const y = [1, 1, 1, 2, 2, 2];
const tree = new DecisionTreeClassifier({ maxDepth: 3 });
tree.fit(X, y);
console.log("predictions:", tree.predict([[1.5, 0], [5.5, 0]]));
import { Graph } from "dyna:structures";
const g = new Graph({ directed: true, weighted: true });
const a = g.addNode(), b = g.addNode(), c = g.addNode();
g.addEdge(a, b, 3);
g.addEdge(b, c, 4);
g.addEdge(a, c, 10);
const dist = g.dijkstra(a);
console.log("shortest a->c:", dist[c]);
import * as oauth from "dyna:oauth2";
import { JWTSign } from "dyna:crypto";
// PKCE S256 — RFC 7636 Appendix B vector
const verifier = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk";
const challenge = oauth.generateCodeChallenge(verifier, "S256");
console.log("challenge ok:", challenge === "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM");
console.log("isValidCodeVerifier:", oauth.isValidCodeVerifier(verifier));
// Authorization URL (auto state, S256 default)
const { url, state } = oauth.buildAuthorizationUrl({
authorizationEndpoint: "https://auth.example.com/authorize",
clientId: "s6BhdRkqt3",
redirectUri: "https://client.example.com/cb",
scope: "read write",
codeChallenge: challenge,
codeChallengeMethod: "S256"
});
console.log("auth url:", url.includes("code_challenge="));
console.log("state ok:", typeof state === "string");
// Bearer + scope + redirect checks
console.log("bearer header:", oauth.buildBearerHeader("mF_9.B5f-4.1JqM"));
console.log("bearer parse:", oauth.parseBearerHeader("Bearer mF_9.B5f-4.1JqM"));
console.log("www:", oauth.buildWWWAuthenticate({ realm: "example", error: "invalid_token" }));
console.log("scope:", oauth.parseScope("read write"), oauth.formatScope(["read","write"]));
console.log("redirect exact:", oauth.isValidRedirectUri("https://client.example.com/cb", ["https://client.example.com/cb"]));
console.log("loopback port-ignore:", oauth.isValidRedirectUri("http://127.0.0.1:54321/cb", ["http://127.0.0.1:8080/cb"]));
console.log("secureCompare:", oauth.secureCompare("abc", "abc"));
// JWT (HS* works without TLS, RS*/ES* needs CONFIG_TLS=y)
const key = new TextEncoder().encode("test-secret-32-bytes-long-xxxxxx");
const now = Math.floor(Date.now()/1000);
const tok = JWTSign({ sub: "u1", aud: "https://api.example.com", exp: now+3600 }, key, { alg: "HS256" });
const payload = oauth.verifyJWT(tok, key, { algorithms: ["HS256"], aud: "https://api.example.com" });
console.log("jwt sub:", payload.sub);
DynaJS is a library first. The engine compiles to libdynajs.a; dynajsc compiles JavaScript to bytecode embedded in a C file, and the engine is statically linked in, so a JavaScript program can ship as a single self-contained native executable with no JS source and no runtime to install on the target:
# examples/hello.js becomes examples/hello — a native binary with no JS source
make examples/hello
./examples/hello
See examples/ for three embedding patterns: static JS compilation (hello.js), ES modules (hello_module.js), and an external native module (fib.c → fib.so). The public headers are src/dynajs.h and src/dyna-libc.h.
# Full engine with the native standard library and TLS
make CONFIG_NATIVE_MODULES=y CONFIG_TLS=y
# Minimal engine
make
Build-configuration flags (all are optional; each selects a feature or a strategy):
| Flag | Effect |
|---|---|
CONFIG_NATIVE_MODULES=y | Compile the dyna:* standard library in |
CONFIG_TLS=y | OpenSSL-backed TLS: HTTPS, RSA/ECDSA, X.509, AEAD ciphers |
CONFIG_SQLITE=y | Force SQLite support (auto-detected via pkg-config otherwise) |
CONFIG_ZSTD=y | Force zstd support (auto-detected) |
CONFIG_IO_URING=y | Linux io_uring async backend |
CONFIG_CLANG=y | Use clang instead of gcc on Linux |
CONFIG_OPENLIBM=y | Link the vendored openlibm for reproducible numerics |
CONFIG_ASAN=y / CONFIG_UBSAN=y / CONFIG_TSAN=y | Sanitizer builds |
CONFIG_ML_NO_SIMD=y | Strictly sequential ML kernels (the oracle control) |
A flag change is not tracked by make; run make clean after changing flags, or a stale object will silently drop conditionally-compiled code.
The gates, cheapest to most expensive:
make test # core engine suite (39 suites, parallel)
make test-native # the 159 native-module suites + examples + docs + installer tests
make test-api # API surface, params, differential, roundtrip, vectors, kernels, properties, fuzz
make test-security # adversarial/pen tests
make prepush # THE pre-push gate: codegraph, clean build, fuzz link proof,
# test, test-native, test-api, test-security, test-repl, TLS
./dev.sh gate # zero-warning build + ASan + UBSan + make test + test262 baseline
bash docker/build-and-test.sh # glibc + musl + emulated amd64, in parallel
make prepush is installed as the pre-push git hook (make install-hooks); it is the one thing to run before anything leaves the machine. ./dev.sh is the developer entry point — ./dev.sh alone lists every subcommand (build, quick, asan, ubsan, t262, bench, rss, amd64, gate, ...).
The docker gates reuse cached toolchain images (dynajs:deps, dynajs:deps-musl, dynajs:deps-amd64) and run the three libc/ISA legs concurrently with persistent object caches, so a warm run recompiles only what changed.
dyna:simd) are a runtime-dispatched portfolio: scalar, NEON, SSE4.2, AVX2, AVX-512, SVE — the fastest kernel the CPU can actually run is chosen at startup and is observable (simd.active()).bench/ holds the benchmark suites (parser, regexp, stdio, numeric, the C cores); each covers the area it is named for. Run the one that covers what you touched.src/ engine + stdlib sources (dyna-*.c per module; src/core/* pure C)
tests/ JS test suites (test_*.js) + shell harnesses (test_*.sh)
examples/ runnable JS examples, embedding demos, fib native module
tools/ code generators, doc/example checkers, api-inventory
bench/ benchmark suites and the code-graph analyzer (bench/codegraph.py)
docker/ container gates: Dockerfile (cached toolchains), build-and-test.sh, linux.sh
docs/ the API reference (API.md) and reports
third_party/ vendored openlibm (linked only with CONFIG_OPENLIBM)
dev.sh the developer entry point (build/asan/ubsan/t262/bench/gate)
install.sh end-user installer (clone, build, install, verify, upgrade)
Makefile single build system: binary, libdynajs.a, every gate target
This section is written for coding agents working in this repository. Read it before editing.
make CONFIG_NATIVE_MODULES=y CONFIG_TLS=y # the canonical dev binary
./dev.sh gate # full proof gate (build+ASan+UBSan+test+test262)
make prepush # the 10-stage pre-push gate (what the git hook runs)
python3 bench/codegraph.py . N # source-shape analyzer; first arg is the ROOT
bash docker/build-and-test.sh # glibc/musl/amd64 legs, parallel, cached images
python3 bench/codegraph.py for source shape (padding, complexity, hand-written link lines).```js block in README.md and API.md against the current binary (make check-readme, make check-api). A documented call must exist and run; a block that cannot run standalone must carry <!-- check:skip --> on the line before its fence. Skipped blocks are counted and printed.tools/doc-lint.sh); internal links must resolve (tools/check-anchors.py).tools/api-inventory.js enumerates the binary's exported names — the API reference is generated against it, and a new export without a test shows up as a gap there.JSFunctionBytecode.debug must stay the LAST member.make clean after changing any CONFIG_* flag.Uint8Array to JS handlers, never a bare ArrayBuffer.Ambient declarations for every dyna:* module, the WHATWG globals, and the core prototype extensions ship in dynajs.d.ts. Reference it from your tsconfig.json / jsconfig.json:
{
"compilerOptions": {
"types": ["dynajs"]
}
}
That gives autocomplete, hover documentation and typechecking over the full standard library — the declarations are generated against the binary's own export inventory and the gate (make check-types) fails when they drift.
5 commits
C
67.9%
JavaScript
27.4%
Python
3.0%
Shell
1.1%
Status: BETA. The core engine is stable and the standard library surface is complete; pre-1.0 releases may change names, options and defaults. Production use is at your own judgement; pin a version (
install.sh --ref <tag>).
DynaJS is an embeddable, high-performance JavaScript engine and runtime: a from-scratch JS engine (ES2023-class surface) with a built-in native standard library (dyna:*), multi-architecture SIMD acceleration, HTTP/TLS networking, data science tooling, and a single static, dependency-free binary for macOS, Linux and FreeBSD.
Everything ships in one binary. There is no node_modules, no runtime dependency, and no package registry — modules are compiled in or linked from the system's security-tracked libraries (OpenSSL, SQLite, zstd, brotli).
Engineering highlights:
./dev.sh gate).Array, String and Number gain the data-wrangling surface that otherwise requires a utility dependency: grouping, keyed sorting, deduplication, sampling, transposition, string case conversion, template formatting, byte-level transforms and human-readable formatting. Implemented as compiled C — no interpreter step per element — with string scanning, counting, matching and RegExp fast paths dispatched through the same runtime-selected SIMD kernels as dyna:simd.fetch/Request/Response/Headers/FormData, WebSockets, an HTTP server with strict JSON-RPC 2.0 endpoints (batched, promise-aware) and an L4 TCP proxy — all driven by the native event reactor on kqueue (macOS/BSD) and epoll (Linux), whose backend fd folds into an outer event loop.dyna:ml ships classifiers, regressors, clustering, decomposition and scalers — decision trees, random forests, k-NN, K-means, DBSCAN, linear/logistic regression, SVMs, gradient boosting, PCA — fitted in C over contiguous doubles, with persistence built in: every fitted model round-trips through serialize()/deserialize() to bit-identical predictions. Train and serve in one process, no Python bridge.simd.active(), so a deployment can audit which code path it runs..env, YAML, JSON5, CSV and XML for configuration and text.libdynajs.a; dynajsc compiles JavaScript to bytecode embedded in a single native executable, with the engine statically linked in — the target needs no JS source and no separate runtime to install.-e one-liner with top-level await, the HTTP server is syscall-bound, and heavy loops run through the SIMD kernels — timings do not depend on optimization history.serialize()/deserialize(), so state moves across a process boundary as bytes.RRule), civil calendar types (PlainDate, PlainDateTime), durations and time zones.One command on macOS, Linux or FreeBSD:
curl -fsSL https://raw.githubusercontent.com/corporatepiyush/dynajs/master/install.sh | bash
The installer clones the source into ~/.cache/dynajs-build, builds from scratch with the full native standard library, and installs one static binary to /usr/local/bin/dynajs (falling back to $HOME/.local/bin when that needs root and sudo is unavailable). It asks no questions, so it is safe to pipe. Re-running it is how you upgrade: it pulls the latest source, rebuilds, and overwrites the old binary. The full build log is kept at ~/.cache/dynajs-build/install.log.
Options:
install.sh --prefix "$HOME/.local" # install to a different prefix
install.sh --ref v1.2.3 # pin a tag instead of master
install.sh --with-deps # also install missing build tools (brew/apt/dnf/...)
install.sh --dry-run # print the plan and preflight report, install nothing
install.sh --uninstall # remove the installed binary
install.sh --verbose # stream the build output
A first install needs git, make and a C compiler (clang preferred). On macOS the Xcode Command Line Tools provide all three. The preflight report says exactly what is missing before anything is downloaded.
// hello.js
import { zstd, unzstd } from "dyna:compress";
const data = new Uint8Array(Array.from({ length: 1000 }, (_, i) => i % 7));
console.log("round trip ok:", unzstd(zstd(data)).every((v, i) => v === data[i]));
dynajs hello.js # run a file
dynajs -e 'print(1 + 1)' # evaluate an expression
dynajs -i # REPL with history, tab-completion and \h help
// Standard WHATWG globals work out of the box
const res = new Response(JSON.stringify({ hello: "world" }), {
status: 200,
headers: { "Content-Type": "application/json" }
});
console.log("Response ok:", res.ok);
res.json().then(data => {
console.log("JSON:", JSON.stringify(data));
});
usage: dynajs [options] [file [args]]
-h --help list options
-e --eval EXPR evaluate EXPR
-i --interactive go to interactive mode
-m --module load as ES6 module (default=autodetect)
--script load as ES6 script (default=autodetect)
--strict force strict mode
-I --include file include an additional file
--std make 'std' and 'os' available to the loaded script
-T --trace trace memory allocation
-d --dump dump the memory usage stats
--no-unhandled-rejection ignore unhandled promise rejections
-s strip all the debug info
--strip-source strip the source code
--io-threads N IO worker threads (default max(ncpu,4); 0 runs
every offload inline, the no-pool control)
-q --quit just instantiate the interpreter and quit
Top-level await works in -e and in scripts, so dynajs -e 'import("dyna:uuid").then(u => print(u.v7()))' is a valid one-liner.
Every module is documented function-by-function in the API reference.
| Module | What it provides |
|---|---|
dyna:bytes | Work with raw binary data: build, slice and search byte buffers, fixed-width reads/writes, hex/base64 views, and UTF-8-safe Text strings |
dyna:cli | Build friendly command-line tools: argument parsing, ANSI-styled output, prompts, progress bars, spinners |
dyna:compress | Squeeze data and pack archives: zstd, brotli, snappy, gzip, LZ4, tar, zip — decompression caps refuse bombs instead of running out of memory |
dyna:config | Read configuration files: TOML 1.0, INI, .env, front matter |
dyna:crypto | Anything secret-dependent: AEAD encryption (AES-GCM, ChaCha20-Poly1305), signatures (RSA, ECDSA, Ed25519), key exchange, password hashing (Argon2id, scrypt, bcrypt), X.509 certificates, JWT |
dyna:csv | Read and write CSV (RFC 4180): streaming, type inference, and a file-backed table |
dyna:dataframe | Columnar data in plain JS: filter, sort, group-by, join, window functions and quantiles over TypedArrays |
dyna:decimal | Exact decimal and money arithmetic (IEEE decimal128, 34 significant digits) — no binary-float rounding surprises |
dyna:encoding | Format everything: charset detection, base64/base32/hex and friends, varints, JSON5, JSONPath, QR codes |
dyna:file | Filesystem work: atomic writes, file locks, watchers, globs, temp files, platform directories |
dyna:hash | Digest data: SHA-1/2, SHA-3, BLAKE2/3, CRC32 (hardware-accelerated), xxHash, fingerprints — one-shot or streaming |
dyna:html | Web content, server-side: an HTML5 tokenizer, CSS-selector queries, a sanitizer, markdown rendering, templating — every context escapes through one audited escaper |
dyna:http | The web platform: WHATWG fetch/Request/Response/Headers/FormData, an HTTP server in a few lines, WebSockets, multipart and header codecs |
dyna:json | Edit JSON documents: JSON Pointer (RFC 6901) lookups, JSON Patch (RFC 6902) with copy-on-write |
dyna:log | Structured logging: one JSON object per line, leveled, grep- and pipe-friendly |
dyna:matcher | Search text fast: Levenshtein edit distance, tries, Bloom filters, Aho-Corasick multi-pattern search, diffs |
dyna:mathx | The math toolbox: statistics, combinatorics, big integers, number theory, linear algebra, interpolation, special functions |
dyna:ml | Train models in-process: trees, forests, k-NN, K-means, DBSCAN, linear/logistic regression, SVMs, gradient boosting, PCA, scalers — C over contiguous doubles |
dyna:net | Everything under HTTP: IP/CIDR arithmetic, TCP/UDP sockets, a DNS client and server, Redis/PostgreSQL/SQLite clients, rate limiting, metrics, an L4 proxy (statically import this or dyna:http, not both) |
dyna:random | Randomness done right: OS-entropy floats, ints, bytes, shuffles, choices — plus a seedable PRNG for reproducible runs |
dyna:schema | Validate data against JSON Schema (Draft 2020-12); schemas compile once, validation is pure dispatch |
dyna:scrape | Crawl politely: robots.txt with token matching, per-host pacing, jittered retries, conditional GETs, RFC 3986 redirect resolution, response caps — the politeness layer that keeps you off blocklists |
dyna:semver | Version numbers done right: semver 2.0.0 parsing, ranges, comparison, incrementing |
dyna:serialize | Binary interchange: protobuf wire codec, ASN.1 DER, MessagePack, CBOR, BSON — for talking to anything that isn't JSON |
dyna:simd | Explicit vector math: reductions, dot products, distances, matrix ops — the fastest kernel your CPU supports, picked at startup |
dyna:structures | The data structures JS never shipped: LRU caches, graphs (Dijkstra, A*, MST, BFS/DFS), heaps, segment trees, disjoint sets, tries |
dyna:sys | Talk to the OS: subprocesses, environment, arguments, CPU/memory facts, terminal formatting |
dyna:time | Dates that work: RFC 5545 recurring events (RRule), Duration, civil calendar types (PlainDate, PlainDateTime), time zones, formatting |
dyna:uring | Linux-only blistering disk I/O: io_uring batches many block reads into one submit/complete cycle per batch (built with CONFIG_IO_URING) |
dyna:url | URLs and domains: WHATWG URL parsing, IDNA 2008/UTS #46, Punycode, form encoding |
dyna:oauth2 | OAuth 2.0 helpers (optional): PKCE S256, state CSRF, bearer auth, WWW-Authenticate, scope & redirect_uri checks — no IO, no JWT dep for HS* |
dyna:uuid | Identifiers: UUID v1–v7 from the OS CSPRNG, plus NanoID and ULID |
dyna:validate | One-line checks: is this an email, a URL, a UUID, a credit card, a semver, an IP? Each a boolean predicate |
dyna:xml | XML parsing — streaming SAX, a tree, or a plain object with XPath-lite access — with sane size caps on by default |
dyna:yaml | YAML 1.2 parsing; anchors and aliases are refused by name, never silently dropped |
Core engine extensions (also in the API reference): Array, String, Number, Object, Date, RegExp extras.
Each of these blocks is executed by the project's own documentation gate, so they are known to run against the current binary.
import { fetch, Request, Response, Headers, AbortController, FormData } from "dyna:http";
// Global fetch is also available on globalThis
const response = await fetch("https://api.example.com/data", {
method: "GET",
headers: { "Accept": "application/json" },
timeout: 5000
});
const data = await response.json();
A real server in a few lines:
import { HTTPServer } from "dyna:http";
const server = new HTTPServer({ port: 8765 });
server.on("request", (req, res) => {
res.json({ route: req.url, method: req.method });
});
server.listen();
// curl http://localhost:8765/hello
import { Bcrypt } from "dyna:crypto";
// Password hashing (shipped in every build)
const hash = Bcrypt.hash("my_secure_password", 10);
const valid = Bcrypt.verify("my_secure_password", hash);
console.log("Bcrypt valid:", valid);
RSA/ECDSA/X.509 exist only in CONFIG_TLS=y builds:
import { RSA, X509 } from "dyna:crypto";
// Key generation and self-signed X.509 certificate
const keypair = RSA.generate(2048);
const certPem = X509.generateSelfSigned({
key: keypair.privateKey,
subject: "localhost",
days: 365
});
const parsed = X509.parse(certPem);
console.log("Cert subject:", parsed.subject);
console.log("Cert serial:", parsed.serialNumber);
import { Schema } from "dyna:schema";
import { Pointer, Patch } from "dyna:json";
// JSON Schema validation (2020-12)
const schema = {
type: "object",
properties: {
id: { type: "integer", minimum: 1 },
name: { type: "string" }
},
required: ["id", "name"]
};
const result = Schema.validate(schema, { id: 10, name: "Alice" });
console.log("Schema valid:", result.valid);
// JSON Pointer (RFC 6901) & Patch (RFC 6902)
const doc = { users: [{ name: "Alice" }, { name: "Bob" }] };
console.log("Pointer read:", Pointer.get(doc, "/users/1/name"));
const patched = Patch.apply(doc, [
{ op: "replace", path: "/users/1/name", value: "Charlie" }
]);
console.log("Patched:", JSON.stringify(patched));
import { TOML } from "dyna:config";
const tomlText = `
title = "DynaJS Config"
[owner]
name = "Admin"
ports = [ 8000, 8001, 8002 ]
`;
const config = TOML.parse(tomlText);
console.log("Config title:", config.title);
console.log("Owner name:", config.owner.name);
const formatted = TOML.stringify(config);
console.log("TOML output length:", formatted.length);
import { URL, domainToASCII, domainToUnicode, punycodeEncode } from "dyna:url";
const url = new URL("https://bücher.example.de/path?q=1#hash");
console.log("Host:", url.host);
console.log("Punycode ASCII:", domainToASCII("bücher.de"));
console.log("Unicode Domain:", domainToUnicode("xn--bcher-kva.de"));
import { RRule } from "dyna:time";
// Weekly meeting every Tuesday for 4 occurrences
const rule = new RRule({
freq: "WEEKLY",
byday: ["TU"],
count: 4,
dtstart: new Date(2026, 7, 18, 10, 0, 0)
});
const dates = rule.all();
console.log("Recurrence count:", dates.length);
import { DataFrame } from "dyna:dataframe";
const df = new DataFrame({
id: new Int32Array([1, 2, 3, 4]),
score: new Float64Array([95.5, 82.0, 88.5, 77.0])
});
console.log("mean:", df.MEAN("score"));
console.log("top scores:", Array.from(df.N_LARGEST("score", 2)));
import { DecisionTreeClassifier } from "dyna:ml";
const X = [[1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0]];
const y = [1, 1, 1, 2, 2, 2];
const tree = new DecisionTreeClassifier({ maxDepth: 3 });
tree.fit(X, y);
console.log("predictions:", tree.predict([[1.5, 0], [5.5, 0]]));
import { Graph } from "dyna:structures";
const g = new Graph({ directed: true, weighted: true });
const a = g.addNode(), b = g.addNode(), c = g.addNode();
g.addEdge(a, b, 3);
g.addEdge(b, c, 4);
g.addEdge(a, c, 10);
const dist = g.dijkstra(a);
console.log("shortest a->c:", dist[c]);
import * as oauth from "dyna:oauth2";
import { JWTSign } from "dyna:crypto";
// PKCE S256 — RFC 7636 Appendix B vector
const verifier = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk";
const challenge = oauth.generateCodeChallenge(verifier, "S256");
console.log("challenge ok:", challenge === "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM");
console.log("isValidCodeVerifier:", oauth.isValidCodeVerifier(verifier));
// Authorization URL (auto state, S256 default)
const { url, state } = oauth.buildAuthorizationUrl({
authorizationEndpoint: "https://auth.example.com/authorize",
clientId: "s6BhdRkqt3",
redirectUri: "https://client.example.com/cb",
scope: "read write",
codeChallenge: challenge,
codeChallengeMethod: "S256"
});
console.log("auth url:", url.includes("code_challenge="));
console.log("state ok:", typeof state === "string");
// Bearer + scope + redirect checks
console.log("bearer header:", oauth.buildBearerHeader("mF_9.B5f-4.1JqM"));
console.log("bearer parse:", oauth.parseBearerHeader("Bearer mF_9.B5f-4.1JqM"));
console.log("www:", oauth.buildWWWAuthenticate({ realm: "example", error: "invalid_token" }));
console.log("scope:", oauth.parseScope("read write"), oauth.formatScope(["read","write"]));
console.log("redirect exact:", oauth.isValidRedirectUri("https://client.example.com/cb", ["https://client.example.com/cb"]));
console.log("loopback port-ignore:", oauth.isValidRedirectUri("http://127.0.0.1:54321/cb", ["http://127.0.0.1:8080/cb"]));
console.log("secureCompare:", oauth.secureCompare("abc", "abc"));
// JWT (HS* works without TLS, RS*/ES* needs CONFIG_TLS=y)
const key = new TextEncoder().encode("test-secret-32-bytes-long-xxxxxx");
const now = Math.floor(Date.now()/1000);
const tok = JWTSign({ sub: "u1", aud: "https://api.example.com", exp: now+3600 }, key, { alg: "HS256" });
const payload = oauth.verifyJWT(tok, key, { algorithms: ["HS256"], aud: "https://api.example.com" });
console.log("jwt sub:", payload.sub);
DynaJS is a library first. The engine compiles to libdynajs.a; dynajsc compiles JavaScript to bytecode embedded in a C file, and the engine is statically linked in, so a JavaScript program can ship as a single self-contained native executable with no JS source and no runtime to install on the target:
# examples/hello.js becomes examples/hello — a native binary with no JS source
make examples/hello
./examples/hello
See examples/ for three embedding patterns: static JS compilation (hello.js), ES modules (hello_module.js), and an external native module (fib.c → fib.so). The public headers are src/dynajs.h and src/dyna-libc.h.
# Full engine with the native standard library and TLS
make CONFIG_NATIVE_MODULES=y CONFIG_TLS=y
# Minimal engine
make
Build-configuration flags (all are optional; each selects a feature or a strategy):
| Flag | Effect |
|---|---|
CONFIG_NATIVE_MODULES=y | Compile the dyna:* standard library in |
CONFIG_TLS=y | OpenSSL-backed TLS: HTTPS, RSA/ECDSA, X.509, AEAD ciphers |
CONFIG_SQLITE=y | Force SQLite support (auto-detected via pkg-config otherwise) |
CONFIG_ZSTD=y | Force zstd support (auto-detected) |
CONFIG_IO_URING=y | Linux io_uring async backend |
CONFIG_CLANG=y | Use clang instead of gcc on Linux |
CONFIG_OPENLIBM=y | Link the vendored openlibm for reproducible numerics |
CONFIG_ASAN=y / CONFIG_UBSAN=y / CONFIG_TSAN=y | Sanitizer builds |
CONFIG_ML_NO_SIMD=y | Strictly sequential ML kernels (the oracle control) |
A flag change is not tracked by make; run make clean after changing flags, or a stale object will silently drop conditionally-compiled code.
The gates, cheapest to most expensive:
make test # core engine suite (39 suites, parallel)
make test-native # the 159 native-module suites + examples + docs + installer tests
make test-api # API surface, params, differential, roundtrip, vectors, kernels, properties, fuzz
make test-security # adversarial/pen tests
make prepush # THE pre-push gate: codegraph, clean build, fuzz link proof,
# test, test-native, test-api, test-security, test-repl, TLS
./dev.sh gate # zero-warning build + ASan + UBSan + make test + test262 baseline
bash docker/build-and-test.sh # glibc + musl + emulated amd64, in parallel
make prepush is installed as the pre-push git hook (make install-hooks); it is the one thing to run before anything leaves the machine. ./dev.sh is the developer entry point — ./dev.sh alone lists every subcommand (build, quick, asan, ubsan, t262, bench, rss, amd64, gate, ...).
The docker gates reuse cached toolchain images (dynajs:deps, dynajs:deps-musl, dynajs:deps-amd64) and run the three libc/ISA legs concurrently with persistent object caches, so a warm run recompiles only what changed.
dyna:simd) are a runtime-dispatched portfolio: scalar, NEON, SSE4.2, AVX2, AVX-512, SVE — the fastest kernel the CPU can actually run is chosen at startup and is observable (simd.active()).bench/ holds the benchmark suites (parser, regexp, stdio, numeric, the C cores); each covers the area it is named for. Run the one that covers what you touched.src/ engine + stdlib sources (dyna-*.c per module; src/core/* pure C)
tests/ JS test suites (test_*.js) + shell harnesses (test_*.sh)
examples/ runnable JS examples, embedding demos, fib native module
tools/ code generators, doc/example checkers, api-inventory
bench/ benchmark suites and the code-graph analyzer (bench/codegraph.py)
docker/ container gates: Dockerfile (cached toolchains), build-and-test.sh, linux.sh
docs/ the API reference (API.md) and reports
third_party/ vendored openlibm (linked only with CONFIG_OPENLIBM)
dev.sh the developer entry point (build/asan/ubsan/t262/bench/gate)
install.sh end-user installer (clone, build, install, verify, upgrade)
Makefile single build system: binary, libdynajs.a, every gate target
This section is written for coding agents working in this repository. Read it before editing.
make CONFIG_NATIVE_MODULES=y CONFIG_TLS=y # the canonical dev binary
./dev.sh gate # full proof gate (build+ASan+UBSan+test+test262)
make prepush # the 10-stage pre-push gate (what the git hook runs)
python3 bench/codegraph.py . N # source-shape analyzer; first arg is the ROOT
bash docker/build-and-test.sh # glibc/musl/amd64 legs, parallel, cached images
python3 bench/codegraph.py for source shape (padding, complexity, hand-written link lines).```js block in README.md and API.md against the current binary (make check-readme, make check-api). A documented call must exist and run; a block that cannot run standalone must carry <!-- check:skip --> on the line before its fence. Skipped blocks are counted and printed.tools/doc-lint.sh); internal links must resolve (tools/check-anchors.py).tools/api-inventory.js enumerates the binary's exported names — the API reference is generated against it, and a new export without a test shows up as a gap there.JSFunctionBytecode.debug must stay the LAST member.make clean after changing any CONFIG_* flag.Uint8Array to JS handlers, never a bare ArrayBuffer.Ambient declarations for every dyna:* module, the WHATWG globals, and the core prototype extensions ship in dynajs.d.ts. Reference it from your tsconfig.json / jsconfig.json:
{
"compilerOptions": {
"types": ["dynajs"]
}
}
That gives autocomplete, hover documentation and typechecking over the full standard library — the declarations are generated against the binary's own export inventory and the gate (make check-types) fails when they drift.
5 commits
C
67.9%
JavaScript
27.4%
Python
3.0%
Shell
1.1%