Implement Error.prototype.toString (ES2026 §20.5.3.4)#557
Conversation
The method was missing from Error.prototype, causing String(error) and template-literal interpolation to throw TypeError after the #527 ToStringLiteral refactor. Define it once on FErrorProto so all NativeError subclasses and user class extends Error inherit it through the prototype chain. Closes #545 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughImplements Error.prototype.toString per ES2026: adds TGocciaGlobals.ErrorPrototypeToString, registers it on Error.prototype (inherited by NativeError subclasses), adds an error message constant for non-object this, tests covering behavior, and documentation noting the prototype method. ChangesError.prototype.toString Implementation
Sequence Diagram(s)(Skipped — changes are internal implementation and tests; no multi-component sequential flow requiring visualization.) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
Benchmark Results407 benchmarks Interpreted: 🟢 33 improved · 🔴 62 regressed · 312 unchanged · avg -0.1% arraybuffer.js — Interp: 🔴 1, 13 unch. · avg -0.5% · Bytecode: 🔴 14 · avg -25.7%
arrays.js — Interp: 🟢 1, 🔴 2, 16 unch. · avg -0.5% · Bytecode: 🔴 19 · avg -28.5%
async-await.js — Interp: 6 unch. · avg -1.2% · Bytecode: 🔴 6 · avg -27.6%
async-generators.js — Interp: 2 unch. · avg -4.1% · Bytecode: 🔴 2 · avg -28.5%
base64.js — Interp: 🟢 1, 9 unch. · avg +0.5% · Bytecode: 🔴 10 · avg -28.8%
classes.js — Interp: 🟢 1, 🔴 1, 29 unch. · avg -0.0% · Bytecode: 🔴 31 · avg -21.0%
closures.js — Interp: 🔴 1, 10 unch. · avg -0.3% · Bytecode: 🔴 11 · avg -28.2%
collections.js — Interp: 12 unch. · avg -0.6% · Bytecode: 🔴 12 · avg -29.1%
csv.js — Interp: 13 unch. · avg -0.2% · Bytecode: 🔴 13 · avg -26.6%
destructuring.js — Interp: 🟢 1, 21 unch. · avg -0.1% · Bytecode: 🔴 22 · avg -26.3%
fibonacci.js — Interp: 🔴 2, 6 unch. · avg -1.2% · Bytecode: 🔴 8 · avg -28.9%
float16array.js — Interp: 🟢 4, 🔴 1, 27 unch. · avg -0.3% · Bytecode: 🔴 32 · avg -26.0%
for-of.js — Interp: 🔴 1, 6 unch. · avg -0.8% · Bytecode: 🔴 7 · avg -26.8%
generators.js — Interp: 🔴 2, 2 unch. · avg -2.8% · Bytecode: 🔴 4 · avg -23.7%
iterators.js — Interp: 🟢 6, 🔴 2, 34 unch. · avg +1.0% · Bytecode: 🔴 42 · avg -21.1%
json.js — Interp: 🟢 2, 🔴 5, 13 unch. · avg -1.5% · Bytecode: 🔴 20 · avg -24.9%
jsx.jsx — Interp: 🔴 4, 17 unch. · avg -2.0% · Bytecode: 🔴 21 · avg -25.2%
modules.js — Interp: 🟢 1, 🔴 3, 5 unch. · avg -1.5% · Bytecode: 🔴 9 · avg -33.4%
numbers.js — Interp: 🔴 6, 5 unch. · avg -3.2% · Bytecode: 🔴 11 · avg -26.4%
objects.js — Interp: 🟢 2, 5 unch. · avg +1.4% · Bytecode: 🔴 7 · avg -27.3%
promises.js — Interp: 🔴 5, 7 unch. · avg -3.3% · Bytecode: 🔴 12 · avg -27.1%
regexp.js — Interp: 🔴 5, 6 unch. · avg -2.1% · Bytecode: 🔴 11 · avg -25.6%
strings.js — Interp: 🔴 1, 18 unch. · avg -0.1% · Bytecode: 🔴 19 · avg -27.0%
tsv.js — Interp: 🔴 1, 8 unch. · avg -1.6% · Bytecode: 🔴 9 · avg -28.8%
typed-arrays.js — Interp: 🟢 5, 🔴 8, 9 unch. · avg +13.7% · Bytecode: 🟢 2, 🔴 19, 1 unch. · avg -25.1%
uint8array-encoding.js — Interp: 🟢 6, 🔴 6, 6 unch. · avg -5.5% · Bytecode: 🔴 18 · avg -30.9%
weak-collections.js — Interp: 🟢 3, 🔴 5, 7 unch. · avg -1.2% · Bytecode: 🟢 7, 🔴 7, 1 unch. · avg -3.7%
Deterministic profile diffDeterministic profile diff: no significant changes. Measured on ubuntu-latest x64. Benchmark ranges compare cached main-branch min/max ops/sec with the PR run; overlapping ranges are treated as unchanged noise. Percentage deltas are secondary context. |
Suite TimingTest Runner (interpreted: 8,817 passed; bytecode: 8,817 passed)
MemoryGC rows aggregate the main thread plus all worker thread-local GCs. Test runner worker shutdown frees thread-local heaps in bulk; that shutdown reclamation is not counted as GC collections or collected objects.
Benchmarks (interpreted: 407; bytecode: 407)
MemoryGC rows aggregate the main thread plus all worker thread-local GCs. Benchmark runner performs explicit between-file collections, so collection and collected-object counts can be much higher than the test runner.
Measured on ubuntu-latest x64. |
…tant Matches the pattern used by Symbol.prototype methods. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
test262 Conformance
Areas closest to 100%
Per-test deltas (+20 / -0)Newly passing (20):
Steady-state failures are non-blocking; regressions vs the cached main baseline (lower total pass count, or any PASS → non-PASS transition) fail the conformance gate. Measured on ubuntu-latest x64, bytecode mode. Areas grouped by the first two test262 path components; minimum 25 attempted tests, areas already at 100% excluded. Δ vs main compares against the most recent cached |
Add gmfNotConstructable flag so `new Error.prototype.toString()` throws "not a constructor" at the call boundary rather than entering the method body. Fixes test262 built-ins/Error/prototype/toString/not-a-constructor. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Error.prototype.toStringonFErrorProtoper ES2026 §20.5.3.4, so all NativeError subclasses and userclass extends Errorinherit it through the prototype chainString(error)and template-literal${error}which threwTypeError: Cannot convert object to primitive valueafter Make ToStringLiteral ES2026-compliant; add ToPropertyKey #527String()coercion, template literals, and TypeError on non-objectthisdocs/built-ins.mdCloses #545
Test plan
tests/built-ins/Error/toString.jstests pass./format.pas --checkclean🤖 Generated with Claude Code