@@ -31,6 +31,7 @@ const {
3131 ObjectDefineProperty,
3232 ObjectDefineProperties,
3333 ObjectKeys,
34+ ObjectPrototype,
3435 RangeError,
3536 ReflectApply,
3637 RegExpPrototypeExec,
@@ -50,8 +51,6 @@ const {
5051 URIError,
5152} = primordials ;
5253
53- const kIsNodeError = Symbol ( 'kIsNodeError' ) ;
54-
5554const isWindows = process . platform === 'win32' ;
5655
5756const messages = new SafeMap ( ) ;
@@ -77,6 +76,8 @@ const MainContextError = Error;
7776const overrideStackTrace = new SafeWeakMap ( ) ;
7877const kNoOverride = Symbol ( 'kNoOverride' ) ;
7978const nodeInternalPrefix = '__node_internal_' ;
79+ const MainContextObjectToString = ObjectPrototype . toString ;
80+
8081const prepareStackTrace = ( globalThis , error , trace ) => {
8182 // API for node internals to override error stack formatting
8283 // without interfering with userland code.
@@ -111,8 +112,13 @@ const prepareStackTrace = (globalThis, error, trace) => {
111112 // at function (file)
112113 // at file
113114 let errorString ;
114- if ( kIsNodeError in error ) {
115- errorString = `${ error . name } [${ error . code } ]: ${ error . message } ` ;
115+ // Do not use primordials here: we intercept user code here.
116+ if ( typeof error . toString === 'function' &&
117+ error . toString !== MainContextObjectToString ) {
118+ errorString = error . toString ( ) ;
119+ if ( errorString === '[Object object]' ) {
120+ errorString = ErrorPrototypeToString ( error ) ;
121+ }
116122 } else {
117123 errorString = ErrorPrototypeToString ( error ) ;
118124 }
@@ -220,8 +226,9 @@ function inspectWithNoCustomRetry(obj, options) {
220226// and may have .path and .dest.
221227class SystemError extends Error {
222228 constructor ( key , context ) {
223- super ( ) ;
224- const prefix = getMessage ( key , [ ] , this ) ;
229+ const msg = messages . get ( key ) ;
230+
231+ const prefix = getMessage ( key , msg , [ ] ) ;
225232 let message = `${ prefix } : ${ context . syscall } returned ` +
226233 `${ context . code } (${ context . message } )` ;
227234
@@ -230,30 +237,18 @@ class SystemError extends Error {
230237 if ( context . dest !== undefined )
231238 message += ` => ${ context . dest } ` ;
232239
240+ super ( message ) ;
241+
233242 this . code = key ;
234243
235244 ObjectDefineProperties ( this , {
236- [ kIsNodeError ] : {
237- __proto__ : null ,
238- value : true ,
239- enumerable : false ,
240- writable : false ,
241- configurable : true ,
242- } ,
243245 name : {
244246 __proto__ : null ,
245247 value : 'SystemError' ,
246248 enumerable : false ,
247249 writable : true ,
248250 configurable : true ,
249251 } ,
250- message : {
251- __proto__ : null ,
252- value : message ,
253- enumerable : false ,
254- writable : true ,
255- configurable : true ,
256- } ,
257252 info : {
258253 __proto__ : null ,
259254 value : context ,
@@ -337,45 +332,53 @@ class SystemError extends Error {
337332}
338333
339334function makeSystemErrorWithCode ( key ) {
340- return class NodeError extends SystemError {
335+ const clazz = class NodeError extends SystemError {
341336 constructor ( ctx ) {
342337 super ( key , ctx ) ;
343338 }
344339 } ;
340+ // The constructor must be the Base class to align with the WPT tests.
341+ SystemError . prototype . constructor = Error ;
342+ return clazz ;
345343}
346344
347- function makeNodeErrorWithCode ( Base , key ) {
348- return function NodeError ( ...args ) {
349- const error = new Base ( ) ;
350- const message = getMessage ( key , args , error ) ;
351- ObjectDefineProperties ( error , {
352- [ kIsNodeError ] : {
353- __proto__ : null ,
354- value : true ,
355- enumerable : false ,
356- writable : false ,
357- configurable : true ,
358- } ,
359- message : {
360- __proto__ : null ,
361- value : message ,
362- enumerable : false ,
363- writable : true ,
364- configurable : true ,
365- } ,
366- toString : {
367- __proto__ : null ,
368- value ( ) {
369- return `${ this . name } [${ key } ]: ${ this . message } ` ;
370- } ,
371- enumerable : false ,
372- writable : true ,
373- configurable : true ,
374- } ,
375- } ) ;
376- error . code = key ;
377- return error ;
378- } ;
345+ function makeNodeErrorWithCode ( Base , key , val ) {
346+ let clazz ;
347+ if ( typeof val === 'string' ) {
348+ clazz = class NodeError extends Base {
349+ constructor ( ...args ) {
350+ const message = getMessage ( key , val , args ) ;
351+ super ( message ) ;
352+ this . code = key ;
353+ }
354+
355+ toString ( ) {
356+ return `${ this . name } [${ key } ]: ${ this . message } ` ;
357+ }
358+ } ;
359+ } else {
360+ clazz = class NodeError extends Base {
361+ constructor ( ...args ) {
362+ super ( ) ;
363+ const message = getFnMessage ( key , val , args , this ) ;
364+ ObjectDefineProperty ( this , 'message' , {
365+ __proto__ : null ,
366+ value : message ,
367+ enumerable : false ,
368+ writable : true ,
369+ configurable : true ,
370+ } ) ;
371+ this . code = key ;
372+ }
373+
374+ toString ( ) {
375+ return `${ this . name } [${ key } ]: ${ this . message } ` ;
376+ }
377+ } ;
378+ }
379+ // The constructor must be the Base class to align with the WPT tests.
380+ clazz . prototype . constructor = Base ;
381+ return clazz ;
379382}
380383
381384/**
@@ -409,32 +412,34 @@ function E(sym, val, def, ...otherClasses) {
409412 if ( def === SystemError ) {
410413 def = makeSystemErrorWithCode ( sym ) ;
411414 } else {
412- def = makeNodeErrorWithCode ( def , sym ) ;
415+ def = makeNodeErrorWithCode ( def , sym , val ) ;
413416 }
414417
415418 if ( otherClasses . length !== 0 ) {
416419 otherClasses . forEach ( ( clazz ) => {
417- def [ clazz . name ] = makeNodeErrorWithCode ( clazz , sym ) ;
420+ def [ clazz . name ] = makeNodeErrorWithCode ( clazz , sym , val ) ;
418421 } ) ;
419422 }
420423 codes [ sym ] = def ;
421424}
422425
423- function getMessage ( key , args , self ) {
424- const msg = messages . get ( key ) ;
425-
426+ function getFnMessage ( key , fn , args , self ) {
426427 assert ??= require ( 'internal/assert' ) ;
427428
428429 const expectedLength = messageArguments . get ( key ) ;
429430
430- if ( typeof msg === 'function' ) {
431- assert (
432- expectedLength <= args . length ,
433- `Code: ${ key } ; The provided arguments length (${ args . length } ) does not ` +
434- `match the required ones (${ expectedLength } ).`
435- ) ;
436- return ReflectApply ( msg , self , args ) ;
437- }
431+ assert (
432+ expectedLength <= args . length ,
433+ `Code: ${ key } ; The provided arguments length (${ args . length } ) does not ` +
434+ `match the required ones (${ expectedLength } ).`
435+ ) ;
436+ return ReflectApply ( fn , self , args ) ;
437+ }
438+
439+ function getMessage ( key , msg , args ) {
440+ assert ??= require ( 'internal/assert' ) ;
441+
442+ const expectedLength = messageArguments . get ( key ) ;
438443
439444 assert (
440445 expectedLength === args . length ,
@@ -858,14 +863,14 @@ module.exports = {
858863 fatalExceptionStackEnhancers,
859864 formatList,
860865 genericNodeError,
866+ messages,
861867 getMessage,
862868 hideInternalStackFrames,
863869 hideStackFrames,
864870 inspectWithNoCustomRetry,
865871 setStackTraceLimit,
866872 isStackOverflowError,
867873 kEnhanceStackBeforeInspector,
868- kIsNodeError,
869874 kNoOverride,
870875 maybeOverridePrepareStackTrace,
871876 overrideStackTrace,
0 commit comments