Skip to content

TypeError stack-trace output diverges from Node — Perry's 'Uncaught exception:' prefix + missing file:line header (regression from v0.5.702 #596) #616

Description

@proggeramlug

Summary

test_issue_462_nullish_property_access.ts and test_issue_510_primitive_method_typeerror.ts both diverge from Node's parity output not because Perry's behavior is wrong, but because Perry's uncaught-exception format doesn't match Node's. Both tests trigger a real TypeError and Perry correctly throws it; the test's UNREACHABLE line correctly never prints. The remaining failure is purely the framing.

This regressed in v0.5.702 (#596 — TypeError throw helpers route through js_throw). The print_uncaught function in crates/perry-runtime/src/exception.rs:159+ was modified at that point to emit a single Uncaught exception: <Name>: <message> line plus the stack string.

Diff (test_issue_462)

Node:
  about to throw — last line of stdout
  file:///Users/.../test_issue_462_nullish_property_access.ts:33
  console.log(undef.foo);
                    ^

  TypeError: Cannot read properties of undefined (reading 'foo')
      at file:///.../test_issue_462_nullish_property_access.ts:33:19
      at ModuleJob.run (node:internal/modules/esm/module_job:430:25)
      ...

Perry:
  about to throw — last line of stdout
  Uncaught exception: TypeError: Cannot read properties of undefined (reading 'foo')
  TypeError: Cannot read properties of undefined (reading 'foo')
      at <anonymous>

Three concrete differences:

  1. Perry has the Uncaught exception: prefix; Node does not.
  2. Perry omits the file:line "header" block (file URL, source-line, caret, blank).
  3. Stack frames differ — Perry's at <anonymous> vs Node's at <file>:<line>:<col> + module-job frames.

Symptom shared by

  • test_issue_462_nullish_property_access
  • test_issue_510_primitive_method_typeerror

(any future test that intentionally throws + lets it escape will hit the same format divergence)

Reproducer

const x: any = undefined;
console.log(x.foo);  // throws TypeError

node --experimental-strip-types repro.ts vs perry repro.ts && ./out produces the diff above.

Suggested approach

If matching Node byte-for-byte is the goal: extend print_uncaught in exception.rs to emit a Node-shaped header. Source-line + caret requires reading the original source text + columns, which the runtime doesn't currently retain at throw time — would need an HIR-side annotation that flows the source-text snippet for the throwing site to the runtime.

If matching Node exactly is unrealistic (Perry's stack frames have a different shape — no module-job, no async-job machinery), an alternative: keep the current Perry format but add it to the parity harness's known-divergence allowlist, so these tests don't show up as failures every sweep.

Environment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugConfirmed defect or regressionparityCompatibility gap with Node.js, ECMAScript, or the supported ecosystem

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions