An experimental, entirely client-side AArch64 / Darwin user-mode execution environment that runs in the browser and deploys as a static site to GitHub Pages.
Live demo: https://communitypokeorg.github.io/darwin-wasm/
This is a research prototype that executes small ARM64 Mach-O programs with a TypeScript interpreter and a minimal Darwin syscall layer. It is not an iOS emulator: no dyld shared cache, no frameworks, no floating point, no Apple code of any kind. Read docs/LIMITATIONS.md before expecting a real iOS binary to run.
- AArch64 interpreter (
src/core/cpu) — the full A64 integer base instruction set (data processing, branches, loads/stores incl. pairs and exclusives,MRS/MSRfor the EL0 registers). Unsupported encodings fault with the PC and word instead of being skipped. Inventory: docs/SUPPORTED_INSTRUCTIONS.md. - Sparse 64-bit memory (
src/core/mem) — 64 KiB pages,MemoryFaulton unmapped access, anonymous allocation formmap. - Mach-O loader (
src/core/macho) — 64-bit LEMH_EXECUTEforCPU_TYPE_ARM64: segments/sections,LC_MAIN/LC_UNIXTHREAD, symbol tables and classicLC_DYLD_INFO_ONLY. Fat, non-ARM64, encrypted and chained-fixup binaries are rejected with an explicit reason. - Mini-dyld + host stubs (
src/core/dyld) — imports are bound to a synthetic trampoline image; a small libc/libSystem subset (puts,printf,malloc,write,exit, …) is implemented in TypeScript on the host side. Unresolved imports are reported, never hidden. - Darwin/XNU syscall layer (
src/core/darwin) —write,exit,mmap/munmap,getpid,gettimeofday,bsdthread_*, Machtask_self/mach_msgstubs and more, using the real Darwinx16dispatch andcerrorcarry-flag convention. Every call is recorded with its class and name for the UI tracker. - Display & input (
src/core/devices) — a 320×240 RGBA framebuffer in guest memory rendered to an HTML5 canvas, and a mouse/touch event queue the guest polls through darwin-wasm extension syscalls. - Web UI (
src/ui, React + Vite) — Mach-O dropzone, sample picker, run/step/pause controls, terminal (stdout/stderr/log), register inspector, disassembly at PC, instruction counter, syscall tracker, dyld report and a permanent honesty banner about what cannot work. - Samples (
public/samples, generated bytools/gen-fixtures.tswith the hand-written encoder intools/asm.ts):hello,math,canvas,syscalls,fault,dyld. No toolchain needed; fixtures are deterministic and checked intotests/fixtures.
Architecture and the planned Rust → WebAssembly backend: docs/ARCHITECTURE.md.
npm ci
npm run dev # Vite dev server
npm test # vitest: decoder, interpreter, memory, Mach-O, dyld, host calls, end-to-end samples
npm run lint # eslint
npm run typecheck # tsc -b
npm run build # static site in dist/ (base path /darwin-wasm/)
npm run fixtures # regenerate tests/fixtures + public/samplesRequires Node 22+. No native toolchain is needed.
.github/workflows/pages.yml runs lint, typecheck, tests and build on every
push to main, then publishes dist/ with actions/deploy-pages. The site
has zero backend dependencies. ci.yml runs the same checks on pull requests.
GitHub Pages must be set to "GitHub Actions" as the source in the repository
settings.
src/core/mem sparse paged memory
src/core/cpu decoder, interpreter, disassembler, CPU state
src/core/macho Mach-O parser/loader
src/core/dyld mini-dyld, host stub trampolines, host calls
src/core/darwin BSD syscalls, Mach traps, extensions, names
src/core/devices framebuffer, input queue
src/core/machine.ts orchestrator + typed events
src/ui React UI
tools ARM64 encoder, Mach-O writer, fixture generator
tests vitest suites + fixtures
docs ARCHITECTURE, SUPPORTED_INSTRUCTIONS, LIMITATIONS, UPSTREAM_REFERENCES
darwin-wasm is MIT licensed (see LICENSE). It contains no Apple code,
firmware or system libraries.
The project structure was informed by
Lakr233/vphone-cli (MIT,
© 2026 @Lakr233) — its Mach-O segment parsing, hand-written ARM64 encoder,
injected-hook approach and "research instrument" UI guidelines. No code was
copied; what was adapted versus rebuilt for the browser is documented in
docs/UPSTREAM_REFERENCES.md. Instruction
semantics follow the Arm Architecture Reference Manual; syscall numbers follow
Apple's open-source XNU syscalls.master.
Runtime dependencies: React (MIT). Build/test: Vite, Vitest, TypeScript, ESLint, Prettier, tsx (all MIT/Apache-2.0).