Skip to content

Commit a232989

Browse files
legendecasrichardlau
authored andcommitted
lib: fix DOMException subclass support
PR-URL: #59680 Backport-PR-URL: #59957 Reviewed-By: Matthew Aitken <maitken033380023@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jordan Harband <ljharb@gmail.com>
1 parent edb9248 commit a232989

File tree

2 files changed

+59
-3
lines changed

2 files changed

+59
-3
lines changed

lib/internal/per_context/domexception.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ const disusedNamesSet = new SafeSet()
6060
.add('NoDataAllowedError')
6161
.add('ValidationError');
6262

63-
let DOMExceptionPrototype;
6463
// The DOMException WebIDL interface defines that:
6564
// - ObjectGetPrototypeOf(DOMException) === Function.
6665
// - ObjectGetPrototypeOf(DOMException.prototype) === Error.prototype.
@@ -75,7 +74,8 @@ class DOMException {
7574
// internal slot.
7675
// eslint-disable-next-line no-restricted-syntax
7776
const self = new Error();
78-
ObjectSetPrototypeOf(self, DOMExceptionPrototype);
77+
// Use `new.target.prototype` to support DOMException subclasses.
78+
ObjectSetPrototypeOf(self, new.target.prototype);
7979
self[transfer_mode_private_symbol] = kCloneable;
8080

8181
if (options && typeof options === 'object') {
@@ -158,7 +158,7 @@ class DOMException {
158158
}
159159
}
160160

161-
DOMExceptionPrototype = DOMException.prototype;
161+
const DOMExceptionPrototype = DOMException.prototype;
162162
ObjectSetPrototypeOf(DOMExceptionPrototype, ErrorPrototype);
163163
ObjectDefineProperties(DOMExceptionPrototype, {
164164
[SymbolToStringTag]: { __proto__: null, configurable: true, value: 'DOMException' },
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
'use strict';
2+
3+
require('../common');
4+
const assert = require('assert');
5+
const { isNativeError } = require('util/types');
6+
7+
class MyDOMException extends DOMException {
8+
ownProp;
9+
#reason;
10+
11+
constructor() {
12+
super('my message', 'NotFoundError');
13+
this.ownProp = 'bar';
14+
this.#reason = 'hello';
15+
}
16+
17+
get reason() {
18+
return this.#reason;
19+
}
20+
}
21+
22+
const myException = new MyDOMException();
23+
// Verifies the prototype chain
24+
assert(myException instanceof MyDOMException);
25+
assert(myException instanceof DOMException);
26+
assert(myException instanceof Error);
27+
// Verifies [[ErrorData]]
28+
assert(isNativeError(myException));
29+
30+
// Verifies subclass properties
31+
assert(Object.hasOwn(myException, 'ownProp'));
32+
assert(!Object.hasOwn(myException, 'reason'));
33+
assert.strictEqual(myException.reason, 'hello');
34+
35+
// Verifies error properties
36+
assert.strictEqual(myException.name, 'NotFoundError');
37+
assert.strictEqual(myException.code, 8);
38+
assert.strictEqual(myException.message, 'my message');
39+
assert.strictEqual(typeof myException.stack, 'string');
40+
41+
// Verify structuredClone only copies known error properties.
42+
const cloned = structuredClone(myException);
43+
assert(!(cloned instanceof MyDOMException));
44+
assert(cloned instanceof DOMException);
45+
assert(cloned instanceof Error);
46+
assert(isNativeError(cloned));
47+
48+
// Verify custom properties
49+
assert(!Object.hasOwn(cloned, 'ownProp'));
50+
assert.strictEqual(cloned.reason, undefined);
51+
52+
// Verify cloned error properties
53+
assert.strictEqual(cloned.name, 'NotFoundError');
54+
assert.strictEqual(cloned.code, 8);
55+
assert.strictEqual(cloned.message, 'my message');
56+
assert.strictEqual(cloned.stack, myException.stack);

0 commit comments

Comments
 (0)