refactor(codemode): give errors a real prototype chain and JS error types - #48559
Merged
Conversation
rekram1-node
force-pushed
the
error-objects-pr
branch
4 times, most recently
from
September 12, 2026 02:10
2a6e7b0 to
b6bfdbb
Compare
rekram1-node
force-pushed
the
error-objects-pr
branch
from
September 12, 2026 02:11
b6bfdbb to
31b2712
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Third step of the value-model rewrite (after #48527, #48541): error values get a real prototype chain, and failures the interpreter raises are named the way JavaScript names them.
The model
The prototypes are intrinsics: a fixed, typed table built once per runtime, the way an engine's
CreateIntrinsicsdoes it.Runnercarriesintrinsics. Each error constructor attaches itself asprototype.constructorwhen the globals are built (QuickJS wires%X.prototype%.constructorthe same way, inJS_NewGlobalCConstructor).createErrorValuetakes the prototype object, not a name, and installs an ownmessageonly when one was given (spec 20.5.1.1).The host boundary serializes errors by brand, not by enumerable own properties (V8
WriteJSErrordoes the same):return new Error("m")andJSON.stringify(new Error("m"))still give{ name: "Error", message: "m" }.Error types
Each interpreter throw site names the JS class the program catches, the way V8 picks
NewTypeErrorvsNewRangeError.TypeErroris the default because nearly every runtime failure is one; the four other classes have factories.class InterpreterRuntimeError { - errorName = "Error" // mutable; overridden with a fluent .as("…") + readonly type: ErrorType = "TypeError" } +export const rangeError = failure("RangeError") +export const referenceError = failure("ReferenceError") +export const syntaxError = failure("SyntaxError") +export const uriError = failure("URIError")TypeErrornull.x,const { a } = undefined,x()on a non-function,tools + 1,atob("!")RangeErrorrangeError(…): invalid array length,Array.without of range,toStringradix,repeatcount, invalidDateReferenceErrorreferenceError(…): unresolved binding, TDZ accessSyntaxErrorsyntaxError(…): badJSON.parseinput, bad regexp flags; unsupported syntax reached at runtimeURIErroruriError(…): malformed URI dataErrorThe agent-facing diagnostic
kind(InvalidDataValue,UnsupportedSyntax, …) is independent of the class..as(…)is gone;Array.withandNumber#toStringradix wereErrorand are now correctlyRangeError;atob/btoano longer invent anInvalidCharacterErrorclass (there is noDOMException).What moved
Behavior that changed
try { const { a } = null } catch (e) { - e.name // "Error" + e.name // "TypeError" - e instanceof TypeError // false + e instanceof TypeError // true } const { constructor } = new RangeError("r") -constructor === RangeError // false — only e.constructor (member access) worked +constructor === RangeError // true -Object.keys(new Error("m")) // ["name", "message"] +Object.keys(new Error("m")) // ["message"] (JS: [] — enumerability flags come later) return new Error("m") // { name: "Error", message: "m" } unchanged new RangeError("r") instanceof Error // true (unchanged)Tests: the
JSON.parse(5)-is-a-plain-Errortest now asserts the rule (null.x,tools + 1→TypeError;class A {}→SyntaxError); the WPTatob/btoatests check forTypeError; the error-serialization tests assert inheritedname/ ownmessage; one new test covers the chain.Results
Array/prototype+language/statementsNext