You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The single biggest platform feature for compiling Bun-specific apps (driver: opencode, but this is what the Bun-native ecosystem standardizes on): a C-ABI FFI layer with the bun:ffi API shape (and optionally Node's experimental node:ffi shape — bun-ffi-structs already bridges both, so one implementation can serve either import).
Evidence from opencode
Everything native in the TUI product funnels through plain C-ABI dylibs — no N-API anywhere (verified: libopentui.dylib from @opentui/core-darwin-arm64@0.4.5 exports 1,775 C symbols, zero napi_* entries; the "node backend" is the same dylib driven via experimental node:ffi):
toArrayBuffer(ptr, byteOffset, byteLength) — 28 uses in opentui — zero-copy JS views over native-owned memory; needs external backing-store support in perry's ArrayBuffer (no GC ownership, explicit lifetime).
CString (read NUL-terminated, encode).
JSCallback / FFIType.function — native→JS callbacks (opentui registers them). Hardest piece: trampoline into perry's JS execution, closure rooting, and a decision on threading (reject cross-thread invocation initially unless opentui proves to need it — verify which callbacks it actually registers before building).
bun-ffi-structs is pure JS over these primitives — free once they exist.
For a native-code runtime, this is natural territory: direct dlopen + call-stub generation (libffi or generated thunks), no JIT trampolines needed.
Suggested bring-up
dlopen + typed calls + ptr on pinned buffers + CString, proven against bun-pty's 17-symbol dylib (spawn a shell, echo round-trip) — small, observable, exercises strings/ints/pointers/read-loop.
toArrayBuffer external backing stores.
JSCallback trampolines.
opentui's 348-symbol table + renderer bring-up (the opencode target tracker owns the app-level milestone).
Acceptance per stage; stage 1 acceptance: a perry-compiled script drives bun-pty end-to-end on macOS-arm64 + linux-x64.
The single biggest platform feature for compiling Bun-specific apps (driver: opencode, but this is what the Bun-native ecosystem standardizes on): a C-ABI FFI layer with the
bun:ffiAPI shape (and optionally Node's experimentalnode:ffishape —bun-ffi-structsalready bridges both, so one implementation can serve either import).Evidence from opencode
Everything native in the TUI product funnels through plain C-ABI dylibs — no N-API anywhere (verified:
libopentui.dylibfrom@opentui/core-darwin-arm64@0.4.5exports 1,775 C symbols, zeronapi_*entries; the "node backend" is the same dylib driven via experimentalnode:ffi):@opentui/core(the TUI renderer)libopentui.dylibper platformYG*) + embedded tree-sitter with bundled grammars (js/ts/markdown/zig)bun-ptylibrust_pty.{dylib,so,dll}(bundled in tarball)@ff-labs/fff-bun@ff-labs/fff-bin-*platform pkgssrc/ffi.tsPrimitives required (from actual usage, not the full spec)
dlopen(path, symbolTable)with typed args/returns —FFIType.{void, ptr, pointer, cstring, bool, i8..i64, u8..u64, usize, f32, f64, function, callback}(observed set in@opentui/coredist).ptr(arrayBufferOrView)— hand JS buffer memory to native. GC design constraint: perry's GC relocates objects (cf. the forwarding-stub/array-growth work, Default GC: array from a direct function call, stored in a variable, is lost when its backing store grows past 32MiB; object arrays get corrupted length #6228/fix(gc): minor sweep reclaimed array-growth forwarding stubs still referenced from old-gen parents #6471) — FFI-exposed buffers must be pinned or allocated in non-moving/off-heap space for their native lifetime.toArrayBuffer(ptr, byteOffset, byteLength)— 28 uses in opentui — zero-copy JS views over native-owned memory; needs external backing-store support in perry's ArrayBuffer (no GC ownership, explicit lifetime).CString(read NUL-terminated, encode).JSCallback/FFIType.function— native→JS callbacks (opentui registers them). Hardest piece: trampoline into perry's JS execution, closure rooting, and a decision on threading (reject cross-thread invocation initially unless opentui proves to need it — verify which callbacks it actually registers before building).bun-ffi-structsis pure JS over these primitives — free once they exist.For a native-code runtime, this is natural territory: direct dlopen + call-stub generation (libffi or generated thunks), no JIT trampolines needed.
Suggested bring-up
ptron pinned buffers +CString, proven against bun-pty's 17-symbol dylib (spawn a shell, echo round-trip) — small, observable, exercises strings/ints/pointers/read-loop.toArrayBufferexternal backing stores.JSCallbacktrampolines.Acceptance per stage; stage 1 acceptance: a perry-compiled script drives bun-pty end-to-end on macOS-arm64 + linux-x64.