mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-14 12:55:16 +08:00
An edge-preserving function whose every return is a walk of its borrowed parameters (accessors such as `node.children`, `t.types`, parent walks, or a call to another such function) now returns its result at +0 from the borrowing body. The result stays reachable from the arguments, so direct callers that consume it as a receiver, a walk, or a borrowable argument use it in place; every other direct caller tests the pending exception and then retains it, before the argument snapshots that keep it reachable are released. The owned adapter retains a present result (a throwing body returns a null dummy, which string and array retains do not accept) before releasing its parameters. Candidates borrow every reference parameter, have no try statements and return a plain reference (instances, records, arrays, strings, nullable-pointer unions). Implementations of a vtable slot that borrows parameters are excluded: virtual dispatch reaches their borrowing body (or its virtual adapter) directly and its callers own the result. Without this, corpus 4545's virtual accessors hit a heap-use-after-free in the sanitized lane. The set grows to a fixpoint, since a call to a borrowed-return function with walk arguments is itself a walk; walk facts are then recomputed with the final set, admitting only parameters whose convention borrows. Walk locals now cover every plain reference type, not only instances. In tsc-ts, compareNodes -> sourceFileOf -> getSourceFileOfNode and maybeTypeOfKind's loop over typesOf(t) no longer touch reference counts.