ReviewOS

home-lang/home

epic: fix JavaScript on the server in the engine — sound types, AOT compilation, threads with shared objects

#814
Open chris opened this 8 days ago ·
8 days ago

JavaScript was never designed for the server. If that doesn't change soon, JavaScript on the server will be replaced by Rust. The fix needs to happen in the engine. Sound types. Ahead-of-time compilation. Threads with shared objects.

JavaScript engines like JavaScriptCore and V8 have some of the best compiler tech in the world. An open question: with sound types, ahead-of-time compilation for statically typed code, and JITs for everything else, can JavaScript be competitive with Rust and C?

In 2011, Google set out to replace JavaScript with Dart, arguing JavaScript couldn't be fixed by evolving it. Then ES2015 shipped. It's time to do that again.

— Jarred Sumner

Home is in a position to make that fix: it has its own TypeScript checker, a Zig port of Bun's runtime, and a native compiler, all in one tree. This epic tracks the work, based on an audit of origin/main @ d4b219507.

Where things stand

  • Sound types. The TS checker matches tsc and nothing stricter; HMxxxx codes exist but are never emitted, and the checker quietly synthesizes any when it can't model something. The runtime strips types. Home's own checker is gradual (Void accepts anything), skips whole statement kinds, and type errors don't stop home build.
  • Ahead-of-time compilation. home build x.home → x64 native works (arm64 is a subset). JS/TS "compile" embeds a bundle into the JIT runtime; nothing lowers TS to native. Native binaries lack PIE, DWARF and a freeing allocator, and Linux releases ship without the JS runtime.
  • Threads with shared objects. JS Workers work (own JSC heap each; sharing via SAB only). The Home language has no working parallelism: spin-only primitives, an executor that doesn't build, no spawn, no atomics, no Send/Sync.

Sound types

  • #778 fix(types): Home checker never checks return, match, block, assert, trait or impl statements
  • #779 fix(types): replace the Void-means-unknown escape hatch with a real Unknown that fails closed
  • #780 fix(cli): make type, parse and import errors fatal in home build / home check
  • #781 feat(types): enforce match exhaustiveness in the checker
  • #782 feat(ts): emit Home-only HMxxxx diagnostics and accept Home options in tsconfig
  • #783 feat(ts): distinguish checker-synthesized any from user-written any
  • #784 feat(ts): opt-in sound mode that closes TypeScript's known unsoundness holes
  • #785 feat(runtime): home run --check refuses to run TypeScript with type errors (and skips checking otherwise)
  • #786 feat(interop): implement the .d.hm and .d.ts loaders so calls across Home ↔ TypeScript are type-checked
  • #787 fix(types): make unsafe a real checked boundary
  • #788 chore(types): wire or delete the unused safety analyses, and make mutable arrays invariant
  • #789 feat(validation): generate runtime validators from types for trust boundaries (validate<T>)

Ahead-of-time compilation

  • #790 refactor(build): retire the LLVM JS/TS launcher that copies home to /tmp and execs it
  • #791 feat(aot): ship the JS/TS runtime in Linux release binaries
  • #792 feat(aot): --compile --target= should cross-compile against Home runtime artifacts, not Bun's npm binaries
  • #793 test(aot): native end-to-end coverage for home build --compile and --bytecode
  • #794 perf(aot): cold-start, RSS and binary-size benchmark for compiled servers
  • #795 feat(codegen): --target=<triple> for regular (non-kernel) native builds
  • #796 feat(codegen): production executable format — PIE, DWARF, libc linkage, object output
  • #797 fix(codegen): real allocator with deallocation in native binaries
  • #798 fix(build): native home build skips comptime, collides module symbols and caches empty blobs
  • #799 feat(codegen): natively compile a Home HTTP server using the stdlib
  • #800 feat(aot): lower type-checked TypeScript (HIR) to native code for a statically resolvable subset
  • #801 refactor(codegen): choose the AOT backbone and retire unwired backends

Threads with shared objects

  • #802 fix(threading): replace spin-only primitives with futex-backed Mutex/CondVar/RwLock/Semaphore
  • #803 fix(threading): honor ThreadAttr, implement CPU affinity and Semaphore.getValue
  • #804 fix(async): get the work-stealing executor building and correct
  • #805 feat(lang): spawn, threads and a multi-core executor in the Home language
  • #806 feat(types): Send/Sync auto traits and thread-aware borrow checking
  • #807 feat(codegen): user-space atomic intrinsics and memory ordering
  • #808 feat(http): multi-core Home HTTP server
  • #809 fix(test): runtime worker tests must prove they ran on Home, not Bun
  • #810 test(runtime): admit the Atomics / SharedArrayBuffer / BroadcastChannel corpus on the native VM across platforms
  • #811 fix(runtime): eval-realm structuredClone and BroadcastChannel mishandle shared memory
  • #812 RFC(runtime): shared objects across JS workers and Home-native threads

Hybrid: AOT for typed code, JIT for everything else

  • #815 feat(aot): run AOT-compiled typed modules alongside the JIT in one process
  • #816 feat(ts): generated entry checks where untyped JS calls sound-typed code
  • #817 RFC(ts): machine number types and fixed-layout structs for sound TypeScript
  • #818 perf(bench): compute benchmarks against Rust and C
  • #819 perf(ts-emit): JIT-friendly JS output driven by sound types

Cross-cutting

  • #813 docs: reconcile AOT, concurrency and safety claims with the code

Already tracked elsewhere

  • #5 arm64 backend (the prerequisite for AOT on Apple Silicon/Graviton)
  • #15, #582, #583, #584 kernel targets and barriers
  • #66 remaining Bun parity items, #465 worker task teardown, #753 CI not running
  • #765, #758, #754, #751 checker any false negatives (related to unmodeled any)
8 days ago

Documentation reconciliation subtask #813 is complete on origin/main via d73153f2c, 610504234, and 9ad690ab9. The stale AOT, standalone-build, HIR, Send/Sync, worker_threads, POSIX-threading, and stdlib-threading claims are now evidence-linked or explicitly marked 🚧/experimental.

8 days ago

Sound-types progress audit: child #820 was already fully implemented on main by fe6535c32 with checker and Program regressions plus frozen-Zod evidence; the stale issue is now closed. No duplicate patch or diagnostic suppression was added.

8 days ago

Sound-types progress: 9a5a46d4c fixes the final known #779 example diagnostic by parsing array[..] as a boundless slice instead of losing the following binding. Parser 1,060/1,060 and focused type artifacts passed under ≤1,024 MB guards. The independent codegen integration failure discovered during verification is tracked as #822.

8 days ago

Cross-cutting cleanup pushed as daa91ed0b: removed codegen’s stale, unwired secondary type-inference bridge and documented the authoritative packages/types checker boundary. This closes #822 and advances #801; codegen tests pass 16/16 at 420 MB guarded peak.

8 days ago

Threads progress: bfe0d9e20 adds Linux current-thread affinity syscalls, public scheduling exports, and a restore-safe Linux round-trip test under #803. Native macOS threading is 22 pass/1 Linux skip at 168 MB; the Linux branch cross-compiles. Windows affinity, priority application, and live Linux execution remain open.

8 days ago

Threading progress: 4e4ec5d is pushed to origin/main and adds Windows processor-group affinity (#803).\n\nThe batch maps CpuSet words to GROUP_AFFINITY without truncation, rejects masks the API cannot represent, adds conversion and platform-gated round-trip coverage, and updates the implementation-status documentation. Native threading is 25/27 with two platform skips (guarded peak 168 MB); x86_64-windows and x86_64-linux scheduler artifacts both cross-compile. No live Windows runtime pass is claimed yet.

8 days ago

Threading acceptance progress: b5c1962 is pushed to origin/main for #803.\n\nspawnWithAttr now has an OS-level child-stack verification test: Linux uses pthread_getattr_np + pthread_attr_getstacksize, and macOS uses pthread_get_stacksize_np. The live macOS suite passed 26/28 with only platform affinity skips (161 MB guarded peak); pthread-backed x86_64-linux and x86_64-windows thread targets both cross-compile. The Linux path is not claimed as runtime-verified yet.

8 days ago

Threading progress: 23b1fcf is pushed to origin/main for #802. Counting semaphore waits now block through Home's shared cross-platform futex and successful posts wake one waiter; an eight-thread contention regression passes. Native threading is 27/29 with only platform affinity skips (192 MB guarded peak), shared futex tests are 3/3, and Linux/Windows module graphs cross-compile. TSan and CPU-utilization gates remain explicitly open.\n\nIssue hygiene in the same goal turn: #754 and #758 were closed as completed after verifying their implementation commits are ancestors of current main and their final child issues are closed.

8 days ago

Threading progress: 0770fb7 is pushed to origin/main for #802. Contended standalone mutexes now block on the shared futex layer, recursive mode is explicitly rejected rather than ignored, and an eight-thread protected-counter regression passes. Native threading is 30/32 with platform affinity skips (194 MB peak), downstream memory is 18/18 (174 MB), and Linux/Windows graphs cross-compile. TSan and CPU-utilization claims remain open.

8 days ago

Threading progress: 9f4d72a is pushed to origin/main for #802. Condition variables now block on a futex epoch, do not remember no-waiter signals, wake one/all correctly, and use real relative OS timeouts while reacquiring the mutex. Native threading passes 34/36 with platform affinity skips (184 MB peak), and Linux/Windows graphs cross-compile. TSan and CPU-utilization gates remain open.

8 days ago

Threading progress: 5bcbbe0 is pushed to origin/main for #802. The read/write lock is now writer-preferring and futex-backed, with eight-reader concurrency and mixed four-reader/four-writer stress coverage. Native threading passes 37/39 with platform affinity skips (161 MB peak), and Linux/Windows graphs cross-compile. TSan and CPU-utilization gates remain open.

8 days ago

Threading progress: 861653684 is pushed to origin/main for #802. The reusable barrier now blocks on the shared futex, rejects zero-party construction, and passes an eight-thread × 100-generation regression. Native threading passes 40/42 with platform affinity skips (167 MB peak), and Linux/Windows graphs cross-compile. All four originally named standalone primitives now block; TSan and CPU-utilization gates remain open.

8 days ago

Threading acceptance progress: 7b987ac is pushed to origin/main for #802. The complete ≥8-thread contention suite passed 100/100 iterations under ThreadSanitizer with zero races/failures and a 203 MB guarded peak. The run is reproducible via scripts/threading-tsan.sh. #802 remains open for measured blocked-waiter CPU utilization only.

8 days ago

Threading umbrella update: #802 is complete and closed.

The final acceptance commit is 5f1238d. Five native measurements with eight semaphore waiters blocked for 250 ms reported a worst per-waiter CPU time of 32 us against a 12,500 us failure limit, with an 82 MB guarded peak. Combined with the prior 100/100 full-suite TSan result in 7b987ac, both #802 acceptance criteria are satisfied.

The full native threading build/test still passes, and the measurement graph cross-compiles for x86_64-linux. Remaining platform-specific threading work continues in #803.

8 days ago

Threading umbrella update: macOS advisory affinity-tag APIs landed in f88e9c1 under #803.

Home now distinguishes macOS THREAD_AFFINITY_POLICY hints from Linux/Windows hard CPU masks and maps XNU KERN_NOT_SUPPORTED to OperationNotSupported. The native suite passed 41/44 with only platform-gated skips at a 152 MB guarded peak; Linux and Windows graphs cross-compiled. #803 remains open for priority and live Linux/Windows validation.

8 days ago

Threading umbrella update: ThreadAttr priority application landed directly on main in 9cbd77b under #803.

Priority is now optional, validated, mapped to Linux nice / Windows thread priority / macOS QoS, and applied before user code with a futex startup handshake that returns OS failures synchronously. Native threading passes 44/47 with platform-only skips at a 168 MB guarded peak; Linux and Windows graphs cross-compile. Remaining #803 work is live Linux and Windows validation.

8 days ago

Async reliability progress: fd820e549 is on main and fixes the queue/deque reclamation and futex parker foundation tracked by #804. Native and TSan suites both pass 20/20; Linux and Windows cross-compilation passes. #804 remains open for runtime scheduling, shutdown, build wiring, and final load acceptance.

8 days ago

Async executor progress: faf992e39 is now on main. It fixes discarded work, stale runtime pointers, the shared worker PRNG race, wake distribution, shutdown/join lifecycle, and task/future reclamation. Native + TSan runtime graphs pass 34/34, including exact completion of 10,000 tasks; Linux/Windows compile checks pass. #804 remains open for package wiring and final load acceptance.

8 days ago

Async executor wiring landed on main in 3629910af. The repaired work-stealing executor now has a public package root, package-local test command, and an umbrella zig build test -Dfilter=async artifact. Direct/package tests pass 35/35 and Linux/Windows compile checks pass. #804 remains open for timer/event integration and final load acceptance.

8 days ago

Concurrency umbrella progress landed directly on main in d45d496. Scheduler and events now use Home futex-backed locks and are registered in the umbrella test graph. Scheduler native 7/7 and events native 5/5 pass; the matching TSan suites pass; both umbrella filters pass; Linux and Windows cross-compilation pass. Tracking issue #804 remains open for its final 1M-task all-core TSan x100 acceptance run.

8 days ago

Executor soak infrastructure and memory-bounded runtime fixes landed directly on main in 70ffd08. Native async 35/35 and TSan async 35/35 pass; umbrella async passes; Linux/Windows compile passes. A full one-million-task TSan run passed exact-once across all 10 workers at an 849 MB peak. #804 remains open while the serial 100-run acceptance soak progresses (1/100 complete).

8 days ago

Issue #804 is now complete and closed. Final acceptance on origin/main: 100/100 serial TSan repetitions passed at 1,000,000 exact-once tasks per run across all 10 workers (100,000,000 tasks total), zero sanitizer findings, 50-56 MB test-process peak, 168 MB compile peak, host low-water above 40%. Native async 35/35, TSan async 35/35, umbrella async/scheduler/events targets, and Linux/Windows cross-compilation all pass. Relevant direct-main commits: 70ffd08 and 947d10e.

8 days ago

#782 is complete on main via df4cfa251b9181e524258858e7c3e8af519a738f. Home-only HM diagnostics now have build-gated process acceptance: real home-tsc --home-sound exact stdout + exit 1, and real home lsp --stdio string wire code HM9001 with source: "home". The opt-in rule registry, tsconfig namespace, CLI flags, driver exit state, and LSP transport are all covered; exact TypeScript parity remains unchanged with Home options off. Full measurements and the guarded-link boundary are recorded in #782.

8 days ago

Dependency progress: 3686d78 landed the internal unmodeled recovery TypeId for #783 and made it relation-compatible with any while preserving a distinct identity. Both ts_checker and HIR package suites pass under the 3,840 MB guard. #783 remains open for source-site migration, reporting, Zod measurement, CI ratchet, and conformance proof.

8 days ago

Sound-mode dependency progress: f22aa8c activates the existing --home-list-unmodeled-any path with source-anchored HM9002 warnings for checker-owned recovery sites. The first migrated site is the expression-depth safety fallback; explicit any remains separate. Full checker/diagnostics suites and the 16/86/586 conformance gates pass under the memory guard. #783 remains open for broader migration and the Zod/CI ratchet acceptance criteria.

8 days ago

Issue #783 advanced in c3b1689cf and afaca5fa0: the byte-pinned full Zod 4.5.2 graph now has a reproducible HM9002 provenance measurement and a per-push/PR CI ceiling. The verified baseline is 0 across exactly 106 production files, with archive SHA-512 enforcement and hermetic equal/lower/growth/integrity controls. README and the parity plan now distinguish this provenance result from the still-open 198-diagnostic full-graph parity gap. #783 remains open for additional source-proven fallback migrations.

8 days ago

Recovery-provenance follow-up pushed directly to main as 49bd3f2. Diagnosed TS2589/TS2590/type-level TS2799 recovery paths now preserve their TypeScript diagnostics while returning traced unmodeled recovery. Full checker and conformance suites pass; the full 106-file Zod gate remains 0 HM9002 / 198 ordinary diagnostics.

8 days ago

TypeScript frontend checkpoint: d67ece5 landed directly on main. It fixes named optional-parameter TS2345 rendering and the nested undefined chain without attaching alias metadata to canonical types. The exact parserharness fixture now passes 1/1, the full checker remains 4,430/4,430, normal conformance remains 16/16 + 86/86 + 586/586, and the revalidated contiguous exact prefix advances to 2,940/2,940. The following 20-case window timed out at its explicit 900-second bound and remains unclaimed/open.

8 days ago

Landed directly on main in c7bf501 (fix(ts): bound recursive program analysis (#814)).

What changed:

  • Suppress only the dependent TS2322 return cascade when the returned declaration annotation already emitted authoritative TS2589; recursiveMappedTypes keeps TS2589 and now matches the upstream baseline.
  • Stop unrelated checked script owners from recursively importing prior owner type graphs. Declaration owners and directly referenced or mergeable globals remain available.
  • Added focused checker and 12-file program regressions.
  • Corrected the earlier partition-only prefix claim in the README/parity plan.

Verification, all serial under HOME_RUN_MAX_MB=3840:

  • full exact leading prefix: 2,960/2,960, peak 1,633 MB
  • exact START=2940 LIMIT=20: 20/20 in 8.0s, peak 474 MB
  • full ts_program: pass, peak 2,241 MB
  • full ts_checker: pass, peak 2,201 MB
  • normal conformance: 16/16 smoke, 86/86 category, 586/586 baseline-aware, peak 2,248 MB
  • Zig formatting and diff checks: pass

The formerly timing-out 21-file parser.asyncGenerators.functionExpressions.es2018 fixture now completes without weakening diagnostics or adding fixture-specific behavior.

Sign in to comment on this issue.