Skip to content

Commit c74c514

Browse files
Uzlopakjasnell
authored andcommitted
errors: fix stacktrace of SystemError
PR-URL: #49956 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Stephen Belanger <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent e266bb1 commit c74c514

File tree

2 files changed

+344
-5
lines changed

2 files changed

+344
-5
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
'use strict';
2+
3+
constcommon=require('../common');
4+
constassert=require('assert');
5+
6+
constbench=common.createBenchmark(main,{
7+
n: [1e6],
8+
code: [
9+
'built-in',
10+
'ERR_FS_CP_DIR_TO_NON_DIR',
11+
],
12+
stackTraceLimit: [0,10],
13+
},{
14+
flags: ['--expose-internals'],
15+
});
16+
17+
functiongetErrorFactory(code){
18+
const{
19+
ERR_FS_CP_DIR_TO_NON_DIR,
20+
}=require('internal/errors').codes;
21+
22+
switch(code){
23+
case'built-in':
24+
return(n)=>newError();
25+
case'ERR_FS_CP_DIR_TO_NON_DIR':
26+
return(n)=>newERR_FS_CP_DIR_TO_NON_DIR({
27+
message: 'cannot overwrite directory',
28+
path: 'dest',
29+
syscall: 'cp',
30+
errno: 21,
31+
code: 'EISDIR',
32+
});
33+
default:
34+
thrownewError(`${code} not supported`);
35+
}
36+
}
37+
38+
functionmain({ n, code, stackTraceLimit }){
39+
constgetError=getErrorFactory(code);
40+
41+
Error.stackTraceLimit=stackTraceLimit;
42+
43+
// Warm up.
44+
constlength=1024;
45+
constarray=[];
46+
for(leti=0;i<length;++i){
47+
array.push(getError(i));
48+
}
49+
50+
bench.start();
51+
52+
for(leti=0;i<n;++i){
53+
constindex=i%length;
54+
array[index]=getError(index);
55+
}
56+
57+
bench.end(n);
58+
59+
// Verify the entries to prevent dead code elimination from making
60+
// the benchmark invalid.
61+
for(leti=0;i<length;++i){
62+
assert.strictEqual(typeofarray[i],'object');
63+
}
64+
}

‎test/parallel/test-errors-systemerror.js‎

Lines changed: 280 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33

44
require('../common');
55
constassert=require('assert');
6-
const{ E, SystemError, codes }=require('internal/errors');
6+
const{ E, SystemError, codes, kIsNodeError }=require('internal/errors');
7+
const{ inspect }=require('internal/util/inspect');
78

89
assert.throws(
910
()=>{newSystemError();},
@@ -31,7 +32,7 @@ const{ERR_TEST } = codes;
3132
code: 'ERR_TEST',
3233
name: 'SystemError',
3334
message: 'custom message: syscall_test returned ETEST (code message)'+
34-
' /str => /str2',
35+
' /str => /str2',
3536
info: ctx
3637
}
3738
);
@@ -51,7 +52,7 @@ const{ERR_TEST } = codes;
5152
code: 'ERR_TEST',
5253
name: 'SystemError',
5354
message: 'custom message: syscall_test returned ETEST (code message)'+
54-
' /buf => /str2',
55+
' /buf => /str2',
5556
info: ctx
5657
}
5758
);
@@ -71,7 +72,7 @@ const{ERR_TEST } = codes;
7172
code: 'ERR_TEST',
7273
name: 'SystemError',
7374
message: 'custom message: syscall_test returned ETEST (code message)'+
74-
' /buf => /buf2',
75+
' /buf => /buf2',
7576
info: ctx
7677
}
7778
);
@@ -110,6 +111,11 @@ const{ERR_TEST } = codes;
110111
assert.strictEqual(err.syscall,'test');
111112
assert.strictEqual(err.path,'path');
112113
assert.strictEqual(err.dest,'path');
114+
115+
assert.strictEqual(err.info.errno,321);
116+
assert.strictEqual(err.info.dest.toString(),'path');
117+
assert.strictEqual(err.info.path.toString(),'path');
118+
assert.strictEqual(err.info.syscall,'test');
113119
}
114120

115121
{
@@ -128,8 +134,277 @@ const{ERR_TEST } = codes;
128134
code: 'ERR_TEST',
129135
name: 'Foobar',
130136
message: 'custom message: syscall_test returned ERR_TEST '+
131-
'(Error occurred)',
137+
'(Error occurred)',
132138
info: ctx
133139
}
134140
);
135141
}
142+
143+
{
144+
constctx={
145+
code: 'ERR',
146+
errno: 123,
147+
message: 'something happened',
148+
syscall: 'syscall_test',
149+
};
150+
consterr=newERR_TEST(ctx);
151+
152+
// is set to true
153+
assert.strictEqual(err[kIsNodeError],true);
154+
155+
// is not writable
156+
assert.throws(
157+
()=>{err[kIsNodeError]=false;},
158+
{
159+
name: 'TypeError',
160+
message: /Symbol\(kIsNodeError\)/,
161+
}
162+
);
163+
164+
// is not enumerable
165+
assert.strictEqual(Object.prototype.propertyIsEnumerable.call(err,kIsNodeError),false);
166+
167+
// is configurable
168+
deleteerr[kIsNodeError];
169+
assert.strictEqual(kIsNodeErrorinerr,false);
170+
}
171+
172+
{
173+
constctx={
174+
code: 'ERR',
175+
errno: 123,
176+
message: 'something happened',
177+
syscall: 'syscall_test',
178+
};
179+
consterr=newERR_TEST(ctx);
180+
181+
// is set to true
182+
assert.strictEqual(err.name,'SystemError');
183+
184+
// is writable
185+
err.name='CustomError';
186+
assert.strictEqual(err.name,'CustomError');
187+
188+
// is not enumerable
189+
assert.strictEqual(Object.prototype.propertyIsEnumerable.call(err,'name'),false);
190+
191+
// is configurable
192+
deleteerr.name;
193+
assert.strictEqual(err.name,'Error');
194+
}
195+
196+
{
197+
constctx={
198+
code: 'ERR',
199+
errno: 123,
200+
message: 'something happened',
201+
syscall: 'syscall_test',
202+
};
203+
consterr=newERR_TEST(ctx);
204+
205+
// Is set with the correct message
206+
assert.strictEqual(err.message,'custom message: syscall_test returned ERR (something happened)');
207+
208+
// is writable
209+
err.message='custom message';
210+
assert.strictEqual(err.message,'custom message');
211+
212+
// is not enumerable
213+
assert.strictEqual(Object.prototype.propertyIsEnumerable.call(err,'message'),false);
214+
215+
// is configurable
216+
deleteerr.message;
217+
assert.strictEqual(err.message,'');
218+
}
219+
220+
{
221+
constctx={
222+
code: 'ERR',
223+
errno: 123,
224+
message: 'something happened',
225+
syscall: 'syscall_test',
226+
};
227+
consterr=newERR_TEST(ctx);
228+
229+
// Is set to the correct syscall
230+
assert.strictEqual(err.syscall,'syscall_test');
231+
232+
// is writable
233+
err.syscall='custom syscall';
234+
assert.strictEqual(err.syscall,'custom syscall');
235+
236+
// is enumerable
237+
assert(Object.prototype.propertyIsEnumerable.call(err,'syscall'));
238+
239+
// is configurable
240+
deleteerr.syscall;
241+
assert.strictEqual('syscall'inerr,false);
242+
}
243+
244+
{
245+
constctx={
246+
code: 'ERR',
247+
errno: 123,
248+
message: 'something happened',
249+
syscall: 'syscall_test',
250+
};
251+
consterr=newERR_TEST(ctx);
252+
253+
// Is set to the correct errno
254+
assert.strictEqual(err.errno,123);
255+
256+
// is writable
257+
err.errno='custom errno';
258+
assert.strictEqual(err.errno,'custom errno');
259+
260+
// is enumerable
261+
assert(Object.prototype.propertyIsEnumerable.call(err,'errno'));
262+
263+
// is configurable
264+
deleteerr.errno;
265+
assert.strictEqual('errno'inerr,false);
266+
}
267+
268+
{
269+
constctx={
270+
code: 'ERR',
271+
errno: 123,
272+
message: 'something happened',
273+
syscall: 'syscall_test',
274+
};
275+
consterr=newERR_TEST(ctx);
276+
277+
// Is set to the correct info
278+
assert.strictEqual(Object.keys(err.info).length,4);
279+
assert.strictEqual(err.info.errno,123);
280+
assert.strictEqual(err.info.code,'ERR');
281+
assert.strictEqual(err.info.message,'something happened');
282+
assert.strictEqual(err.info.syscall,'syscall_test');
283+
284+
// is not writable
285+
assert.throws(
286+
()=>{
287+
err.info={
288+
...ctx,
289+
errno: 124
290+
};
291+
},
292+
{
293+
name: 'TypeError',
294+
message: /'info'/,
295+
}
296+
);
297+
298+
assert.strictEqual(Object.keys(err.info).length,4);
299+
assert.strictEqual(err.info.errno,123);
300+
assert.strictEqual(err.info.code,'ERR');
301+
assert.strictEqual(err.info.message,'something happened');
302+
assert.strictEqual(err.info.syscall,'syscall_test');
303+
304+
// is enumerable
305+
assert(Object.prototype.propertyIsEnumerable.call(err,'info'));
306+
307+
// is configurable
308+
deleteerr.info;
309+
310+
assert.strictEqual('info'inerr,false);
311+
}
312+
313+
{
314+
// Make sure the stack trace does not contain SystemError
315+
try{
316+
thrownewERR_TEST({
317+
code: 'ERR',
318+
errno: 123,
319+
message: 'something happened',
320+
syscall: 'syscall_test',
321+
});
322+
}catch(e){
323+
assert.doesNotMatch(e.stack,/atnewSystemError/);
324+
assert.match(e.stack.split('\n')[1],/test-errors-systemerror\.js/);
325+
}
326+
}
327+
328+
{
329+
// Make sure the stack trace has the correct number of frames
330+
constlimit=Error.stackTraceLimit;
331+
Error.stackTraceLimit=3;
332+
functiona(){
333+
b();
334+
}
335+
336+
functionb(){
337+
c();
338+
}
339+
340+
functionc(){
341+
thrownewERR_TEST({
342+
code: 'ERR',
343+
errno: 123,
344+
message: 'something happened',
345+
syscall: 'syscall_test',
346+
});
347+
}
348+
try{
349+
a();
350+
}catch(e){
351+
assert.doesNotMatch(e.stack,/atnewSystemError/);
352+
assert.match(e.stack.split('\n')[1],/test-errors-systemerror\.js/);
353+
assert.match(e.stack.split('\n')[1],/atc\(/);
354+
assert.match(e.stack.split('\n')[2],/test-errors-systemerror\.js/);
355+
assert.match(e.stack.split('\n')[2],/atb\(/);
356+
assert.match(e.stack.split('\n')[3],/test-errors-systemerror\.js/);
357+
assert.match(e.stack.split('\n')[3],/ata\(/);
358+
assert.strictEqual(e.stack.split('\n').length,4);
359+
}finally{
360+
Error.stackTraceLimit=limit;
361+
}
362+
}
363+
364+
{
365+
// Inspect should return the correct string
366+
consterr=newERR_TEST({
367+
code: 'ERR',
368+
errno: 123,
369+
message: 'something happened',
370+
syscall: 'syscall_test',
371+
custom: 'custom'
372+
});
373+
letinspectedErr=inspect(err);
374+
375+
assert.ok(inspectedErr.includes(`info:{
376+
code: 'ERR',
377+
errno: 123,
378+
message: 'something happened',
379+
syscall: 'syscall_test',
380+
custom: 'custom'
381+
},`));
382+
383+
err.syscall='custom_syscall';
384+
385+
inspectedErr=inspect(err);
386+
387+
assert.ok(inspectedErr.includes(`info:{
388+
code: 'ERR',
389+
errno: 123,
390+
message: 'something happened',
391+
syscall: 'custom_syscall',
392+
custom: 'custom'
393+
},`));
394+
}
395+
396+
{
397+
// toString should return the correct string
398+
399+
consterr=newERR_TEST({
400+
code: 'ERR',
401+
errno: 123,
402+
message: 'something happened',
403+
syscall: 'syscall_test',
404+
});
405+
406+
assert.strictEqual(
407+
err.toString(),
408+
'SystemError [ERR_TEST]: custom message: syscall_test returned ERR (something happened)'
409+
);
410+
}

0 commit comments

Comments
(0)