Files
scriptc/tests/corpus/stack-overflow-uncaught.ts
Chris Tate 3bcf761f42 Throw a catchable RangeError on deep recursion
Native executables used to terminate with a signal when recursion
exhausted the stack. Functions that can take part in unbounded recursion
now compare the stack pointer against a per-stack guard on entry and
throw Node's `RangeError: Maximum call stack size exceeded` through the
ordinary exception path, so catch handlers, finally blocks, worker error
events and the uncaught-error exit code behave as they do under Node.

- The checked set is every function on a cycle of the call graph, where
  operations that can reenter compiled code indirectly (indirect calls,
  callbacks, dynamic and library operations) reach closure targets and
  class members. Non-recursive functions, including leaf callbacks, stay
  check-free, and the may-throw analysis accounts for the new throw.
- The runtime installs the guard per context (main thread from the stack
  rlimit, workers from their thread attributes) and per async fiber, with
  a reserve for the throw, unwinding and error reporting. Worker threads
  now get an explicit 8 MiB stack.
- Scalar call results pass through the unwind path as its dummy value, so
  calls in tail position keep tail-call and recursion elimination.
2026-10-09 16:55:35 -05:00

17 lines
426 B
TypeScript

// @exit: 1
// An uncaught stack-overflow RangeError ends the process with Node's
// uncaught exit code; output written before it still matches.
function climb(n: number): number {
return climb(n + 1) + 1;
}
console.log("start");
try {
climb(0);
} catch (e) {
console.log("first", (e as Error).name);
}
process.on("exit", (code) => console.log("exit", code));
console.log("again");
climb(0);
console.log("unreachable");