1
1
'use strict' ;
2
2
3
3
const {
4
- ErrorCaptureStackTrace ,
4
+ Error ,
5
5
ErrorPrototype,
6
6
ObjectDefineProperties,
7
7
ObjectDefineProperty,
@@ -60,20 +60,33 @@ const disusedNamesSet = new SafeSet()
60
60
. add ( 'NoDataAllowedError' )
61
61
. add ( 'ValidationError' ) ;
62
62
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
63
72
class DOMException {
64
73
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 ;
67
80
68
81
if ( options && typeof options === 'object' ) {
69
82
const { name } = options ;
70
- internalsMap . set ( this , {
83
+ internalsMap . set ( self , {
71
84
message : `${ message } ` ,
72
85
name : `${ name } ` ,
73
86
} ) ;
74
87
75
88
if ( 'cause' in options ) {
76
- ObjectDefineProperty ( this , 'cause' , {
89
+ ObjectDefineProperty ( self , 'cause' , {
77
90
__proto__ : null ,
78
91
value : options . cause ,
79
92
configurable : true ,
@@ -82,11 +95,14 @@ class DOMException {
82
95
} ) ;
83
96
}
84
97
} else {
85
- internalsMap . set ( this , {
98
+ internalsMap . set ( self , {
86
99
message : `${ message } ` ,
87
100
name : `${ options } ` ,
88
101
} ) ;
89
102
}
103
+ // Return the error object as the return overriding of the constructor.
104
+ // eslint-disable-next-line no-constructor-return
105
+ return self ;
90
106
}
91
107
92
108
[ messaging_clone_symbol ] ( ) {
@@ -142,8 +158,9 @@ class DOMException {
142
158
}
143
159
}
144
160
145
- ObjectSetPrototypeOf ( DOMException . prototype , ErrorPrototype ) ;
146
- ObjectDefineProperties ( DOMException . prototype , {
161
+ DOMExceptionPrototype = DOMException . prototype ;
162
+ ObjectSetPrototypeOf ( DOMExceptionPrototype , ErrorPrototype ) ;
163
+ ObjectDefineProperties ( DOMExceptionPrototype , {
147
164
[ SymbolToStringTag ] : { __proto__ : null , configurable : true , value : 'DOMException' } ,
148
165
name : { __proto__ : null , enumerable : true , configurable : true } ,
149
166
message : { __proto__ : null , enumerable : true , configurable : true } ,
@@ -181,7 +198,7 @@ for (const { 0: name, 1: codeName, 2: value } of [
181
198
] ) {
182
199
const desc = { enumerable : true , value } ;
183
200
ObjectDefineProperty ( DOMException , codeName , desc ) ;
184
- ObjectDefineProperty ( DOMException . prototype , codeName , desc ) ;
201
+ ObjectDefineProperty ( DOMExceptionPrototype , codeName , desc ) ;
185
202
nameToCodeMap . set ( name , value ) ;
186
203
}
187
204
0 commit comments