Skip to content

fix(runtime): preserve Error heritage across class factory evaluations - #9946

Closed
proggeramlug wants to merge 2 commits into
PerryTS:mainfrom
proggeramlug:fix/9940-compile-package-error-identity
Closed

fix(runtime): preserve Error heritage across class factory evaluations#9946
proggeramlug wants to merge 2 commits into
PerryTS:mainfrom
proggeramlug:fix/9940-compile-package-error-identity

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

A compilePackages constructor factory could evaluate one nested class template with different parents. Later evaluations overwrote the shared class-id parent registry, so an earlier Error-backed instance failed instanceof Error even though its recorded prototype chain still contained Error. Zod 4's $constructor follows this pattern, causing Hono to treat validation errors like thrown strings.

This change makes an object's recorded class-evaluation prototype authoritative for instanceof Error, then falls back to the existing shared class-id metadata for ordinary instances. The regression fixture compiles a source package that evaluates the same dynamic class with Object, Error, then Object parents.

Fixes #9940.

Validation:

  • new issue_9940_compile_package_error_identity regression: passes; baseline output was false true true, fixed output is true true true
  • Zod 4.4.3 reproduction: 80 native modules compiled; zod instanceof ZodError, zod instanceof Error, app subclass, and plain Error all report true
  • targeted Error/class-expression/dynamic-heritage tests: 17 passed
  • perry-runtime: 3,259 passed, 4 ignored; doc tests passed
  • scripts/run_lint_gates.sh: all 66 gates passed, 2 CI-only commands skipped
  • exact PR changeset-fragment check passed

Summary by CodeRabbit

  • Bug Fixes
    • Fixed instanceof Error behavior for error subclasses created through compiled packages.
    • Error instances now retain the correct global Error identity, including after repeated class evaluations.
    • Added coverage to verify package-defined, application-defined, and standard errors are recognized consistently.

@coderabbitai

coderabbitai Bot commented Sep 7, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: c89f541d-2fcb-47d4-abc3-a692c7e97b32

📥 Commits

Reviewing files that changed from the base of the PR and between 616a2cb and bb077b0.

📒 Files selected for processing (3)
  • changelog.d/9946-compile-package-error-identity.md
  • crates/perry-runtime/src/object/instanceof.rs
  • crates/perry/tests/issue_9940_compile_package_error_identity.rs

Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

The runtime now checks recorded prototype chains when evaluating instanceof Error. A new integration test verifies Error subclasses from compilePackages dependencies retain the global Error identity.

Changes

Error identity resolution

Layer / File(s) Summary
Runtime Error matching and regression coverage
crates/perry-runtime/src/object/instanceof.rs, crates/perry/tests/issue_9940_compile_package_error_identity.rs, changelog.d/9946-compile-package-error-identity.md
js_instanceof checks the recorded prototype chain before the class registry fallback. The integration test verifies package errors, application errors, and plain errors all return true for instanceof Error. The changelog records the fix.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to bb077

Dependency-generated Error subclasses now retain global Error identity after repeated dynamic class evaluation, restoring framework error handling without an identified remaining merge risk.

Suggested reviewers: jdalton

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 2 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the runtime fix for preserving Error inheritance across class factory evaluations.
Description check ✅ Passed The description explains the bug, the implementation approach, the linked issue, and validation results. It does not reproduce the template headings or checklist, but it contains the required substant…
Linked Issues check ✅ Passed The changes address issue [#9940] by preserving recorded Error heritage for compilePackages-generated classes, retaining fallback behavior for ordinary instances, and adding a regression test for glob…
Out of Scope Changes check ✅ Passed The runtime change, regression test, and changelog entry are directly related to the Error identity bug and the requirements in [#9940]. No unrelated code changes are identified.
Full details: Docstring Coverage

Explanation

Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 2 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jdalton jdalton left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of bb077b0a43a0936ff7dc893bf252bf5bc32447b9 (2026-09-07).

The per-evaluation prototype check in js_instanceof addresses the shared-class-ID overwrite directly. Please extend the regression to cover the false result as well: create an Object-backed instance from the same factory, evaluate the Error-backed factory, and assert the earlier plain instance is still not an Error. Also test an Error-backed instance created before the subsequent Object evaluation. The new early return treats Some(false) as authoritative, so a positive-only true true true assertion leaves half of that contract uncovered. This is a coverage request; I did not establish a defect in the implementation.

Validation scope: source/diff inspection; I have not run this PR's build or test suite locally.

@proggeramlug
proggeramlug marked this pull request as ready for review September 7, 2026 04:33
@proggeramlug

Copy link
Copy Markdown
Contributor Author

Landed on main via merge train #9959. Validated as a tree: 67/67 lint gates, and perry-runtime/codegen/hir/stdlib all green (5,968 tests, 0 failures). Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A class extending Error inside a compilePackages dependency fails instanceof Error — Hono's onError never sees a ZodError

2 participants