lib: fix DOMException subclass support

PR-URL: https://github.com/nodejs/node/pull/59680
Reviewed-By: Matthew Aitken <maitken033380023@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Jordan Harband <ljharb@gmail.com>
This commit is contained in:
Chengzhong Wu 2025-08-31 18:20:02 +01:00 committed by GitHub
parent 494909b4f8
commit dddc4a5972
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 58 additions and 3 deletions

View File

@ -60,7 +60,6 @@ const disusedNamesSet = new SafeSet()
.add('NoDataAllowedError')
.add('ValidationError');
let DOMExceptionPrototype;
// The DOMException WebIDL interface defines that:
// - ObjectGetPrototypeOf(DOMException) === Function.
// - ObjectGetPrototypeOf(DOMException.prototype) === Error.prototype.
@ -75,7 +74,8 @@ class DOMException {
// internal slot.
// eslint-disable-next-line no-restricted-syntax
const self = new Error();
ObjectSetPrototypeOf(self, DOMExceptionPrototype);
// Use `new.target.prototype` to support DOMException subclasses.
ObjectSetPrototypeOf(self, new.target.prototype);
self[transfer_mode_private_symbol] = kCloneable;
if (options && typeof options === 'object') {
@ -158,7 +158,7 @@ class DOMException {
}
}
DOMExceptionPrototype = DOMException.prototype;
const DOMExceptionPrototype = DOMException.prototype;
ObjectSetPrototypeOf(DOMExceptionPrototype, ErrorPrototype);
ObjectDefineProperties(DOMExceptionPrototype, {
[SymbolToStringTag]: { __proto__: null, configurable: true, value: 'DOMException' },

View File

@ -0,0 +1,55 @@
'use strict';
require('../common');
const assert = require('assert');
class MyDOMException extends DOMException {
ownProp;
#reason;
constructor() {
super('my message', 'NotFoundError');
this.ownProp = 'bar';
this.#reason = 'hello';
}
get reason() {
return this.#reason;
}
}
const myException = new MyDOMException();
// Verifies the prototype chain
assert(myException instanceof MyDOMException);
assert(myException instanceof DOMException);
assert(myException instanceof Error);
// Verifies [[ErrorData]]
assert(Error.isError(myException));
// Verifies subclass properties
assert(Object.hasOwn(myException, 'ownProp'));
assert(!Object.hasOwn(myException, 'reason'));
assert.strictEqual(myException.reason, 'hello');
// Verifies error properties
assert.strictEqual(myException.name, 'NotFoundError');
assert.strictEqual(myException.code, 8);
assert.strictEqual(myException.message, 'my message');
assert.strictEqual(typeof myException.stack, 'string');
// Verify structuredClone only copies known error properties.
const cloned = structuredClone(myException);
assert(!(cloned instanceof MyDOMException));
assert(cloned instanceof DOMException);
assert(cloned instanceof Error);
assert(Error.isError(cloned));
// Verify custom properties
assert(!Object.hasOwn(cloned, 'ownProp'));
assert.strictEqual(cloned.reason, undefined);
// Verify cloned error properties
assert.strictEqual(cloned.name, 'NotFoundError');
assert.strictEqual(cloned.code, 8);
assert.strictEqual(cloned.message, 'my message');
assert.strictEqual(cloned.stack, myException.stack);