@@ -14,6 +14,7 @@ const {
14
14
AggregateError,
15
15
ArrayFrom,
16
16
ArrayIsArray,
17
+ ArrayPrototypeFilter,
17
18
ArrayPrototypeIncludes,
18
19
ArrayPrototypeIndexOf,
19
20
ArrayPrototypeJoin,
@@ -116,6 +117,11 @@ const prepareStackTrace = (globalThis, error, trace) => {
116
117
// Error: Message
117
118
// at function (file)
118
119
// at file
120
+ const code = 'code' in error ? error . code : null ;
121
+ if ( code && overrideStackTraceByCode . has ( code ) ) {
122
+ const f = overrideStackTraceByCode . get ( code ) ;
123
+ return f ( error , trace ) ;
124
+ }
119
125
const errorString = ErrorPrototypeToString ( error ) ;
120
126
if ( trace . length === 0 ) {
121
127
return errorString ;
@@ -186,14 +192,16 @@ function lazyBuffer() {
186
192
return buffer ;
187
193
}
188
194
189
- const addCodeToName = hideStackFrames ( function addCodeToName ( err , name , code ) {
195
+ const addCodeToName = hideStackFrames ( function addCodeToName ( err , name , code ,
196
+ deferStack ) {
190
197
// Set the stack
191
198
err = captureLargerStackTrace ( err ) ;
192
199
// Add the error code to the name to include it in the stack trace.
193
200
err . name = `${ name } [${ code } ]` ;
194
201
// Access the stack to generate the error message including the error code
195
202
// from the name.
196
- err . stack ; // eslint-disable-line no-unused-expressions
203
+ if ( ! deferStack )
204
+ err . stack ; // eslint-disable-line no-unused-expressions
197
205
// Reset the name to the actual name.
198
206
if ( name === 'SystemError' ) {
199
207
ObjectDefineProperty ( err , 'name' , {
@@ -248,7 +256,7 @@ class SystemError extends Error {
248
256
writable : true ,
249
257
configurable : true
250
258
} ) ;
251
- addCodeToName ( this , 'SystemError' , key ) ;
259
+ addCodeToName ( this , 'SystemError' , key , false ) ;
252
260
253
261
this . code = key ;
254
262
@@ -338,7 +346,7 @@ function makeSystemErrorWithCode(key) {
338
346
} ;
339
347
}
340
348
341
- function makeNodeErrorWithCode ( Base , key ) {
349
+ function makeNodeErrorWithCode ( Base , key , deferStack ) {
342
350
return function NodeError ( ...args ) {
343
351
const limit = Error . stackTraceLimit ;
344
352
if ( isErrorStackTraceLimitWritable ( ) ) Error . stackTraceLimit = 0 ;
@@ -360,7 +368,7 @@ function makeNodeErrorWithCode(Base, key) {
360
368
writable : true ,
361
369
configurable : true ,
362
370
} ) ;
363
- addCodeToName ( error , Base . name , key ) ;
371
+ addCodeToName ( error , Base . name , key , deferStack ) ;
364
372
error . code = key ;
365
373
return error ;
366
374
} ;
@@ -382,18 +390,19 @@ function hideStackFrames(fn) {
382
390
// Utility function for registering the error codes. Only used here. Exported
383
391
// *only* to allow for testing.
384
392
function E ( sym , val , def , ...otherClasses ) {
393
+ const deferStack = overrideStackTraceByCode . has ( sym ) ;
385
394
// Special case for SystemError that formats the error message differently
386
395
// The SystemErrors only have SystemError as their base classes.
387
396
messages . set ( sym , val ) ;
388
397
if ( def === SystemError ) {
389
398
def = makeSystemErrorWithCode ( sym ) ;
390
399
} else {
391
- def = makeNodeErrorWithCode ( def , sym ) ;
400
+ def = makeNodeErrorWithCode ( def , sym , deferStack ) ;
392
401
}
393
402
394
403
if ( otherClasses . length !== 0 ) {
395
404
otherClasses . forEach ( ( clazz ) => {
396
- def [ clazz . name ] = makeNodeErrorWithCode ( clazz , sym ) ;
405
+ def [ clazz . name ] = makeNodeErrorWithCode ( clazz , sym , deferStack ) ;
397
406
} ) ;
398
407
}
399
408
codes [ sym ] = def ;
@@ -781,6 +790,40 @@ const fatalExceptionStackEnhancers = {
781
790
}
782
791
} ;
783
792
793
+ // Ensures the printed error line is from user code.
794
+ let _kArrowMessagePrivateSymbol , _setHiddenValue ;
795
+ function setArrowMessage ( err , arrowMessage ) {
796
+ if ( ! _kArrowMessagePrivateSymbol ) {
797
+ ( {
798
+ arrow_message_private_symbol : _kArrowMessagePrivateSymbol ,
799
+ setHiddenValue : _setHiddenValue ,
800
+ } = internalBinding ( 'util' ) ) ;
801
+ }
802
+ _setHiddenValue ( err , _kArrowMessagePrivateSymbol , arrowMessage ) ;
803
+ }
804
+
805
+ // Hide stack lines before the first user code line.
806
+ function hideLeadingInternalFrames ( error , stackFrames ) {
807
+ let frames = stackFrames ;
808
+ if ( typeof stackFrames === 'object' ) {
809
+ let beforeUserCode = true ;
810
+ frames = ArrayPrototypeFilter (
811
+ stackFrames ,
812
+ ( frm ) => {
813
+ if ( ! beforeUserCode )
814
+ return true ;
815
+ const isInternal = StringPrototypeStartsWith ( frm . getFileName ( ) ,
816
+ 'node:internal' ) ;
817
+ if ( ! isInternal )
818
+ beforeUserCode = false ;
819
+ return ! isInternal ;
820
+ } ,
821
+ ) ;
822
+ }
823
+ ArrayPrototypeUnshift ( frames , error ) ;
824
+ return ArrayPrototypeJoin ( frames , '\n at ' ) ;
825
+ }
826
+
784
827
// Node uses an AbortError that isn't exactly the same as the DOMException
785
828
// to make usage of the error in userland and readable-stream easier.
786
829
// It is a regular error with `.code` and `.name`.
@@ -802,6 +845,7 @@ module.exports = {
802
845
hideStackFrames,
803
846
isErrorStackTraceLimitWritable,
804
847
isStackOverflowError,
848
+ setArrowMessage,
805
849
connResetException,
806
850
uvErrmapGet,
807
851
uvException,
@@ -834,6 +878,12 @@ module.exports = {
834
878
// Note: Please try to keep these in alphabetical order
835
879
//
836
880
// Note: Node.js specific errors must begin with the prefix ERR_
881
+
882
+ // Custom error stack overrides.
883
+ const overrideStackTraceByCode = new SafeMap ( [
884
+ [ 'ERR_REQUIRE_ESM' , hideLeadingInternalFrames ] ,
885
+ ] ) ;
886
+
837
887
E ( 'ERR_AMBIGUOUS_ARGUMENT' , 'The "%s" argument is ambiguous. %s' , TypeError ) ;
838
888
E ( 'ERR_ARG_NOT_ITERABLE' , '%s must be iterable' , TypeError ) ;
839
889
E ( 'ERR_ASSERTION' , '%s' , Error ) ;
@@ -1397,23 +1447,31 @@ E('ERR_PERFORMANCE_INVALID_TIMESTAMP',
1397
1447
'%d is not a valid timestamp' , TypeError ) ;
1398
1448
E ( 'ERR_PERFORMANCE_MEASURE_INVALID_OPTIONS' , '%s' , TypeError ) ;
1399
1449
E ( 'ERR_REQUIRE_ESM' ,
1400
- ( filename , parentPath = null , packageJsonPath = null ) => {
1401
- let msg = `Must use import to load ES Module: ${ filename } ` ;
1402
- if ( parentPath && packageJsonPath ) {
1403
- const path = require ( 'path' ) ;
1404
- const basename = path . basename ( filename ) === path . basename ( parentPath ) ?
1405
- filename : path . basename ( filename ) ;
1406
- msg +=
1407
- '\nrequire() of ES modules is not supported.\nrequire() of ' +
1408
- ` ${ filename } from ${ parentPath } ` +
1409
- 'is an ES module file as it is a .js file whose nearest parent ' +
1410
- 'package.json contains "type": "module" which defines all .js ' +
1411
- 'files in that package scope as ES modules.\nInstead rename ' +
1412
- ` ${ basename } to end in .cjs, change the requiring code to use ` +
1413
- 'import(), or remove "type": "module" from ' +
1414
- ` ${ packageJsonPath } .\n` ;
1450
+ function ( filename , hasEsmSyntax , parentPath = null , packageJsonPath = null ) {
1451
+ let msg = `require() of ES Module ${ filename } ${ parentPath ? ` from ${
1452
+ parentPath } ` : '' } not supported.` ;
1453
+ if ( ! packageJsonPath ) {
1454
+ if ( filename . endsWith ( '.mjs' ) )
1455
+ msg += `\nInstead change the require of ${ filename } to a dynamic ` +
1456
+ 'import() which is available in all CommonJS modules.' ;
1457
+ return msg ;
1458
+ }
1459
+ const path = require ( 'path' ) ;
1460
+ const basename = path . basename ( filename ) === path . basename ( parentPath ) ?
1461
+ filename : path . basename ( filename ) ;
1462
+ if ( hasEsmSyntax ) {
1463
+ msg += `\nInstead change the require of ${ basename } in ${ parentPath } to` +
1464
+ ' a dynamic import() which is available in all CommonJS modules.' ;
1415
1465
return msg ;
1416
1466
}
1467
+ msg += `\n${ basename } is treated as an ES module file as it is a .js ` +
1468
+ 'file whose nearest parent package.json contains "type": "module" ' +
1469
+ 'which declares all .js files in that package scope as ES modules.' +
1470
+ `\nInstead rename ${ basename } to end in .cjs, change the requiring ` +
1471
+ 'code to use dynamic import() which is available in all CommonJS' +
1472
+ `modules, or remove "type": "module" from ${ packageJsonPath } to ` +
1473
+ 'treat all .js files as CommonJS (using .mjs for all ES modules ' +
1474
+ 'instead).\n' ;
1417
1475
return msg ;
1418
1476
} , Error ) ;
1419
1477
E ( 'ERR_SCRIPT_EXECUTION_INTERRUPTED' ,
0 commit comments