11'use strict' ;
22
33const {
4- ErrorCaptureStackTrace ,
4+ Error ,
55 ErrorPrototype,
66 ObjectDefineProperties,
77 ObjectDefineProperty,
@@ -60,20 +60,33 @@ const disusedNamesSet = new SafeSet()
6060 . add ( 'NoDataAllowedError' )
6161 . add ( 'ValidationError' ) ;
6262
63+ let DOMExceptionPrototype ;
64+ // The DOMException WebIDL interface defines that:
65+ // - ObjectGetPrototypeOf(DOMException) === Function.
66+ // - ObjectGetPrototypeOf(DOMException.prototype) === Error.prototype.
67+ // Thus, we can not simply use the pattern of `class DOMException extends Error` and call
68+ // `super()` to construct an object. The `super` in `super()` call in the constructor will
69+ // be resolved to `Function`, instead of `Error`. Use the trick of return overriding to
70+ // create an object with the `[[ErrorData]]` internal slot.
71+ // Ref: https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#sec-getsuperconstructor
6372class DOMException {
6473 constructor ( message = '' , options = 'Error' ) {
65- this [ transfer_mode_private_symbol ] = kCloneable ;
66- ErrorCaptureStackTrace ( this ) ;
74+ // Invokes the Error constructor to create an object with the [[ErrorData]]
75+ // internal slot.
76+ // eslint-disable-next-line no-restricted-syntax
77+ const self = new Error ( ) ;
78+ ObjectSetPrototypeOf ( self , DOMExceptionPrototype ) ;
79+ self [ transfer_mode_private_symbol ] = kCloneable ;
6780
6881 if ( options && typeof options === 'object' ) {
6982 const { name } = options ;
70- internalsMap . set ( this , {
83+ internalsMap . set ( self , {
7184 message : `${ message } ` ,
7285 name : `${ name } ` ,
7386 } ) ;
7487
7588 if ( 'cause' in options ) {
76- ObjectDefineProperty ( this , 'cause' , {
89+ ObjectDefineProperty ( self , 'cause' , {
7790 __proto__ : null ,
7891 value : options . cause ,
7992 configurable : true ,
@@ -82,11 +95,14 @@ class DOMException {
8295 } ) ;
8396 }
8497 } else {
85- internalsMap . set ( this , {
98+ internalsMap . set ( self , {
8699 message : `${ message } ` ,
87100 name : `${ options } ` ,
88101 } ) ;
89102 }
103+ // Return the error object as the return overriding of the constructor.
104+ // eslint-disable-next-line no-constructor-return
105+ return self ;
90106 }
91107
92108 [ messaging_clone_symbol ] ( ) {
@@ -142,8 +158,9 @@ class DOMException {
142158 }
143159}
144160
145- ObjectSetPrototypeOf ( DOMException . prototype , ErrorPrototype ) ;
146- ObjectDefineProperties ( DOMException . prototype , {
161+ DOMExceptionPrototype = DOMException . prototype ;
162+ ObjectSetPrototypeOf ( DOMExceptionPrototype , ErrorPrototype ) ;
163+ ObjectDefineProperties ( DOMExceptionPrototype , {
147164 [ SymbolToStringTag ] : { __proto__ : null , configurable : true , value : 'DOMException' } ,
148165 name : { __proto__ : null , enumerable : true , configurable : true } ,
149166 message : { __proto__ : null , enumerable : true , configurable : true } ,
@@ -181,7 +198,7 @@ for (const { 0: name, 1: codeName, 2: value } of [
181198] ) {
182199 const desc = { enumerable : true , value } ;
183200 ObjectDefineProperty ( DOMException , codeName , desc ) ;
184- ObjectDefineProperty ( DOMException . prototype , codeName , desc ) ;
201+ ObjectDefineProperty ( DOMExceptionPrototype , codeName , desc ) ;
185202 nameToCodeMap . set ( name , value ) ;
186203}
187204
0 commit comments