mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-26 06:34:20 +08:00
unionNarrow, downcast and caughtNarrow extracted a payload as the arm, class or caught kind TypeScript's narrowing proved, with no runtime check. A wrong proof read the payload as another type. Each extraction now verifies its proof once: the union tag (for a two-arm union, that the value does not hold the other arm, which LLVM folds under either dominating test), the target's vtable preorder intervals (shared with instanceof), or the caught kind or class (shared with caughtTest). A mismatch calls scr_trap with an internal-error message from a cold block. A correct program never reaches it: narrowings the frontend cannot prove already lower to checked extraction, which throws the catchable TypeError, and analyses treat these expressions as non-throwing, so a failing guard aborts instead of unwinding. The guards found a stale narrowing the stability analysis missed: a binding initialized or assigned from a narrowed read whose narrowing a callback invalidated inherits that narrowing (`const held: Expr = current`). main segfaults on that program where Node throws a TypeError. NarrowingStability now treats such bindings like captured mutable ones, so their narrowed reads use checked extraction. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>