Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
lib: make domexception a native error
Co-Authored-By: Kenta Moriuchi <moriken@kimamass.com>
PR-URL: #58691
Backport-PR-URL: #59957
Fixes: #56497
Refs: v8/v8@e3df60f
Refs: #58138
Reviewed-By: Jason Zhang <xzha4350@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
Reviewed-By: Ethan Arrowood <ethan@arrowood.dev>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
2 people authored and Renegade334 committed Sep 21, 2025
commit f8d135782bdd3e06964fa782c86201d99eb10e99
35 changes: 26 additions & 9 deletions lib/internal/per_context/domexception.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

const {
ErrorCaptureStackTrace,
Error,
ErrorPrototype,
ObjectDefineProperties,
ObjectDefineProperty,
Expand Down Expand Up @@ -60,20 +60,33 @@ const disusedNamesSet = new SafeSet()
.add('NoDataAllowedError')
.add('ValidationError');

let DOMExceptionPrototype;
// The DOMException WebIDL interface defines that:
// - ObjectGetPrototypeOf(DOMException) === Function.
// - ObjectGetPrototypeOf(DOMException.prototype) === Error.prototype.
// Thus, we can not simply use the pattern of `class DOMException extends Error` and call
// `super()` to construct an object. The `super` in `super()` call in the constructor will
// be resolved to `Function`, instead of `Error`. Use the trick of return overriding to
// create an object with the `[[ErrorData]]` internal slot.
// Ref: https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-getsuperconstructor
class DOMException {
constructor(message = '', options = 'Error') {
this[transfer_mode_private_symbol] = kCloneable;
ErrorCaptureStackTrace(this);
// Invokes the Error constructor to create an object with the [[ErrorData]]
// internal slot.
// eslint-disable-next-line no-restricted-syntax
const self = new Error();
ObjectSetPrototypeOf(self, DOMExceptionPrototype);
self[transfer_mode_private_symbol] = kCloneable;

if (options && typeof options === 'object') {
const { name } = options;
internalsMap.set(this, {
internalsMap.set(self, {
message: `${message}`,
name: `${name}`,
});

if ('cause' in options) {
ObjectDefineProperty(this, 'cause', {
ObjectDefineProperty(self, 'cause', {
__proto__: null,
value: options.cause,
configurable: true,
Expand All @@ -82,11 +95,14 @@ class DOMException {
});
}
} else {
internalsMap.set(this, {
internalsMap.set(self, {
message: `${message}`,
name: `${options}`,
});
}
// Return the error object as the return overriding of the constructor.
// eslint-disable-next-line no-constructor-return
return self;
}

[messaging_clone_symbol]() {
Expand Down Expand Up @@ -142,8 +158,9 @@ class DOMException {
}
}

ObjectSetPrototypeOf(DOMException.prototype, ErrorPrototype);
ObjectDefineProperties(DOMException.prototype, {
DOMExceptionPrototype = DOMException.prototype;
ObjectSetPrototypeOf(DOMExceptionPrototype, ErrorPrototype);
ObjectDefineProperties(DOMExceptionPrototype, {
[SymbolToStringTag]: { __proto__: null, configurable: true, value: 'DOMException' },
name: { __proto__: null, enumerable: true, configurable: true },
message: { __proto__: null, enumerable: true, configurable: true },
Expand Down Expand Up @@ -181,7 +198,7 @@ for (const { 0: name, 1: codeName, 2: value } of [
]) {
const desc = { enumerable: true, value };
ObjectDefineProperty(DOMException, codeName, desc);
ObjectDefineProperty(DOMException.prototype, codeName, desc);
ObjectDefineProperty(DOMExceptionPrototype, codeName, desc);
nameToCodeMap.set(name, value);
}

Expand Down
Loading