statIsFile and statIsDirectory throw ENOENT on a missing path, and
host_profile pins that contract, so a program has no way to ask "is it
there?" without crashing on the answer "no". kyX (metadatastician/kyx)
needs exactly that before reading its inputs and writing its outputs, to
exit with its documented usage status instead of an uncaught stack trace.
pathExists lowers to fs.existsSync: true for any existing path, false for a
missing one, never a throw. The stat predicates are unchanged. It is
declared in stdlib/Deno.affine beside them (the builtins<->stdlib
consistency test requires the declaration), and host_profile now asserts
pathExists is false for the removed file and true for a directory.
Tests: tools/run_codegen_bun_tests.sh fails without the builtin and passes
with it; dune build @test/runtest is green (570 tests).
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_0136P7ZnvMV5Ghe7LUf3oc6N
Summary
statIsFileandstatIsDirectorythrow ENOENT on a missing path, andhost_profilepins that contract. That leaves a Bun-ESM program no way to ask "does this path exist?" without crashing on the answer "no". kyX (metadatastician/kyx) needs exactly that check before it reads inputs and writes outputs. Without it, a missing input gives an uncaught stack trace and the wrong exit status.Changes
lib/codegen_deno.ml: new Bun builtinpathExists→fs.existsSync(path). It is true for any existing path, false for a missing one, and never throws. The stat predicates are unchanged; I chose not to flip their pinned ENOENT contract.stdlib/Deno.affine:pub extern fn pathExists(path: String) -> Bool, declared beside the stat externs, which is what the builtins↔stdlib consistency test requires.tests/codegen-bun/host_profile.{affine,harness.mjs}:pathExistsis false for the removed file and true for a directory.Testing
tools/run_codegen_bun_tests.sh: fails without the builtin, passes with it (2 harnesses).dune build @test/runtest: green, 570 tests.Generated by Claude Code