shell: throw instead of panic on ReadableStream redirect
Passing a ReadableStream as a redirect target in Bun Shell aborts the whole process when the command resolves to a spawned subprocess:
import { $ } from "bun";
await $`cat < ${new Response("hello").body}`;
// panic: TODO SHELL READABLE STREAM
The builtin path (echo hi > ${stream}) already threw Unknown JS value used in shell: [object ReadableStream]. The subprocess path in Cmd::init_subproc_redirections instead had a literal panic!("TODO SHELL READABLE STREAM") that ran before any direction check, so every direction (<, >, 2>) aborted. On POSIX cat and cp are posix_disabled builtins, so they always take the subprocess path; any spawned command hits it too.
Fix
src/runtime/shell/states/Cmd.rs: drop theReadableStreamplaceholder branch so the value falls through to the existingUnknown JS value used in shellthrow, matchingBuiltin::init_redirections.src/runtime/shell/Yield.rs,src/runtime/shell/interpreter.rs: onYield::Failedthe trampoline now callsInterpreter::reject_pending_exceptionand returns immediately instead of draining pipelines. That method takes the pending exception, rejects the ShellPromise with it, and releases the event-loop keepalive. It is guarded by arejectedflag onInterpreterFlagsso a secondYield::Failedreached from a separate.run()invocation (e.g. anIOWritererror loop) swallows the follow-up exception instead of reporting it as unhandled.has_pending_activityis left pinned because a pipeline sibling's subprocess / glob task / builtin threadpool task may still hold a raw*mut Interpreter.src/js/builtins/shell.ts: the cachedrejectcallback was never invoked from native; repurpose it to forward the error value straight to the promise reject so the caller'scatchreceives the thrown error.
Known limitation
spawned-cmd | throwing-cmd (a pipeline sibling that already spawned before the throw) leaves the interpreter GC-pinned and the sibling's pipe read-end held open. If the sibling writes more than the socketpair buffer (~64KB) it blocks in write(2) and the process hangs after the catch fires. The builtin variant of this already hung on main pre-PR. Resolving it soundly needs a detach-then-release walk (close unwrapped pipe ends, kill/detach live subprocesses, cancel in-flight shell tasks, then release the pin), which belongs in a follow-up alongside #30550.
Verification
8 cases added to bunshell.test.ts (stdin / stdout / stderr to subprocess, Response.body, pipeline with Bun.gc(true), first-in-pipeline, both-sides-of-pipeline, && async re-entry). Each spawns a child that catches the error and asserts a clean exit.
USE_SYSTEM_BUN=1 bun test bunshell.test.ts -t "ReadableStream as redirect" # 8 fail (SIGABRT / exit 134)
bun bd test bunshell.test.ts -t "ReadableStream as redirect" # 8 pass
Full bunshell.test.ts is green (394 pass, 0 fail).
Related: #18262. #30550 is the full implementation of ReadableStream as shell stdin; this change is the minimal safety fix so the placeholder no longer crashes the process in the meantime.