| // Flags: --expose-internals |
| 'use strict'; |
| |
| require('../common'); |
| const assert = require('assert'); |
| const { E, SystemError, codes, kIsNodeError } = require('internal/errors'); |
| const { inspect } = require('internal/util/inspect'); |
| |
| assert.throws( |
| () => { new SystemError(); }, |
| { |
| name: 'TypeError', |
| message: "Cannot read properties of undefined (reading 'syscall')", |
| } |
| ); |
| |
| E('ERR_TEST', 'custom message', SystemError); |
| const { ERR_TEST } = codes; |
| |
| { |
| const ctx = { |
| code: 'ETEST', |
| message: 'code message', |
| syscall: 'syscall_test', |
| path: '/str', |
| dest: '/str2' |
| }; |
| |
| assert.throws( |
| () => { throw new ERR_TEST(ctx); }, |
| { |
| code: 'ERR_TEST', |
| name: 'SystemError', |
| message: 'custom message: syscall_test returned ETEST (code message)' + |
| ' /str => /str2', |
| info: ctx |
| } |
| ); |
| } |
| |
| { |
| const ctx = { |
| code: 'ETEST', |
| message: 'code message', |
| syscall: 'syscall_test', |
| path: Buffer.from('/buf'), |
| dest: '/str2' |
| }; |
| assert.throws( |
| () => { throw new ERR_TEST(ctx); }, |
| { |
| code: 'ERR_TEST', |
| name: 'SystemError', |
| message: 'custom message: syscall_test returned ETEST (code message)' + |
| ' /buf => /str2', |
| info: ctx |
| } |
| ); |
| } |
| |
| { |
| const ctx = { |
| code: 'ETEST', |
| message: 'code message', |
| syscall: 'syscall_test', |
| path: Buffer.from('/buf'), |
| dest: Buffer.from('/buf2') |
| }; |
| assert.throws( |
| () => { throw new ERR_TEST(ctx); }, |
| { |
| code: 'ERR_TEST', |
| name: 'SystemError', |
| message: 'custom message: syscall_test returned ETEST (code message)' + |
| ' /buf => /buf2', |
| info: ctx |
| } |
| ); |
| } |
| |
| { |
| const ctx = { |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'syscall_test', |
| path: Buffer.from('a'), |
| dest: Buffer.from('b') |
| }; |
| const err = new ERR_TEST(ctx); |
| assert.strictEqual(err.info, ctx); |
| assert.strictEqual(err.code, 'ERR_TEST'); |
| err.code = 'test'; |
| assert.strictEqual(err.code, 'test'); |
| |
| // Test legacy properties. These shouldn't be used anymore |
| // but let us make sure they still work |
| assert.strictEqual(err.errno, 123); |
| assert.strictEqual(err.syscall, 'syscall_test'); |
| assert.strictEqual(err.path, 'a'); |
| assert.strictEqual(err.dest, 'b'); |
| |
| // Make sure it's mutable |
| err.code = 'test'; |
| err.errno = 321; |
| err.syscall = 'test'; |
| err.path = 'path'; |
| err.dest = 'path'; |
| |
| assert.strictEqual(err.errno, 321); |
| assert.strictEqual(err.syscall, 'test'); |
| assert.strictEqual(err.path, 'path'); |
| assert.strictEqual(err.dest, 'path'); |
| |
| assert.strictEqual(err.info.errno, 321); |
| assert.strictEqual(err.info.dest.toString(), 'path'); |
| assert.strictEqual(err.info.path.toString(), 'path'); |
| assert.strictEqual(err.info.syscall, 'test'); |
| } |
| |
| { |
| const ctx = { |
| code: 'ERR_TEST', |
| message: 'Error occurred', |
| syscall: 'syscall_test' |
| }; |
| assert.throws( |
| () => { |
| const err = new ERR_TEST(ctx); |
| err.name = 'Foobar'; |
| throw err; |
| }, |
| { |
| code: 'ERR_TEST', |
| name: 'Foobar', |
| message: 'custom message: syscall_test returned ERR_TEST ' + |
| '(Error occurred)', |
| info: ctx |
| } |
| ); |
| } |
| |
| { |
| const ctx = { |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'syscall_test', |
| }; |
| const err = new ERR_TEST(ctx); |
| |
| // is set to true |
| assert.strictEqual(err[kIsNodeError], true); |
| |
| // is not writable |
| assert.throws( |
| () => { err[kIsNodeError] = false; }, |
| { |
| name: 'TypeError', |
| message: /Symbol\(kIsNodeError\)/, |
| } |
| ); |
| |
| // is not enumerable |
| assert.strictEqual(Object.prototype.propertyIsEnumerable.call(err, kIsNodeError), false); |
| |
| // is configurable |
| delete err[kIsNodeError]; |
| assert.strictEqual(kIsNodeError in err, false); |
| } |
| |
| { |
| const ctx = { |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'syscall_test', |
| }; |
| const err = new ERR_TEST(ctx); |
| |
| // is set to true |
| assert.strictEqual(err.name, 'SystemError'); |
| |
| // is writable |
| err.name = 'CustomError'; |
| assert.strictEqual(err.name, 'CustomError'); |
| |
| // is not enumerable |
| assert.strictEqual(Object.prototype.propertyIsEnumerable.call(err, 'name'), false); |
| |
| // is configurable |
| delete err.name; |
| assert.strictEqual(err.name, 'Error'); |
| } |
| |
| { |
| const ctx = { |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'syscall_test', |
| }; |
| const err = new ERR_TEST(ctx); |
| |
| // Is set with the correct message |
| assert.strictEqual(err.message, 'custom message: syscall_test returned ERR (something happened)'); |
| |
| // is writable |
| err.message = 'custom message'; |
| assert.strictEqual(err.message, 'custom message'); |
| |
| // is not enumerable |
| assert.strictEqual(Object.prototype.propertyIsEnumerable.call(err, 'message'), false); |
| |
| // is configurable |
| delete err.message; |
| assert.strictEqual(err.message, ''); |
| } |
| |
| { |
| const ctx = { |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'syscall_test', |
| }; |
| const err = new ERR_TEST(ctx); |
| |
| // Is set to the correct syscall |
| assert.strictEqual(err.syscall, 'syscall_test'); |
| |
| // is writable |
| err.syscall = 'custom syscall'; |
| assert.strictEqual(err.syscall, 'custom syscall'); |
| |
| // is enumerable |
| assert(Object.prototype.propertyIsEnumerable.call(err, 'syscall')); |
| |
| // is configurable |
| delete err.syscall; |
| assert.strictEqual('syscall' in err, false); |
| } |
| |
| { |
| const ctx = { |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'syscall_test', |
| }; |
| const err = new ERR_TEST(ctx); |
| |
| // Is set to the correct errno |
| assert.strictEqual(err.errno, 123); |
| |
| // is writable |
| err.errno = 'custom errno'; |
| assert.strictEqual(err.errno, 'custom errno'); |
| |
| // is enumerable |
| assert(Object.prototype.propertyIsEnumerable.call(err, 'errno')); |
| |
| // is configurable |
| delete err.errno; |
| assert.strictEqual('errno' in err, false); |
| } |
| |
| { |
| const ctx = { |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'syscall_test', |
| }; |
| const err = new ERR_TEST(ctx); |
| |
| // Is set to the correct info |
| assert.strictEqual(Object.keys(err.info).length, 4); |
| assert.strictEqual(err.info.errno, 123); |
| assert.strictEqual(err.info.code, 'ERR'); |
| assert.strictEqual(err.info.message, 'something happened'); |
| assert.strictEqual(err.info.syscall, 'syscall_test'); |
| |
| // is not writable |
| assert.throws( |
| () => { |
| err.info = { |
| ...ctx, |
| errno: 124 |
| }; |
| }, |
| { |
| name: 'TypeError', |
| message: /'info'/, |
| } |
| ); |
| |
| assert.strictEqual(Object.keys(err.info).length, 4); |
| assert.strictEqual(err.info.errno, 123); |
| assert.strictEqual(err.info.code, 'ERR'); |
| assert.strictEqual(err.info.message, 'something happened'); |
| assert.strictEqual(err.info.syscall, 'syscall_test'); |
| |
| // is enumerable |
| assert(Object.prototype.propertyIsEnumerable.call(err, 'info')); |
| |
| // is configurable |
| delete err.info; |
| |
| assert.strictEqual('info' in err, false); |
| } |
| |
| { |
| // Make sure the stack trace does not contain SystemError |
| try { |
| throw new ERR_TEST({ |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'syscall_test', |
| }); |
| } catch (e) { |
| assert.doesNotMatch(e.stack, /at new SystemError/); |
| assert.match(e.stack.split('\n')[1], /test-errors-systemerror\.js/); |
| } |
| } |
| |
| { |
| // Make sure the stack trace has the correct number of frames |
| const limit = Error.stackTraceLimit; |
| Error.stackTraceLimit = 3; |
| function a() { |
| b(); |
| } |
| |
| function b() { |
| c(); |
| } |
| |
| function c() { |
| throw new ERR_TEST({ |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'syscall_test', |
| }); |
| } |
| try { |
| a(); |
| } catch (e) { |
| assert.doesNotMatch(e.stack, /at new SystemError/); |
| assert.match(e.stack.split('\n')[1], /test-errors-systemerror\.js/); |
| assert.match(e.stack.split('\n')[1], /at c \(/); |
| assert.match(e.stack.split('\n')[2], /test-errors-systemerror\.js/); |
| assert.match(e.stack.split('\n')[2], /at b \(/); |
| assert.match(e.stack.split('\n')[3], /test-errors-systemerror\.js/); |
| assert.match(e.stack.split('\n')[3], /at a \(/); |
| assert.strictEqual(e.stack.split('\n').length, 4); |
| } finally { |
| Error.stackTraceLimit = limit; |
| } |
| } |
| |
| { |
| // Inspect should return the correct string |
| const err = new ERR_TEST({ |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'syscall_test', |
| custom: 'custom' |
| }); |
| let inspectedErr = inspect(err); |
| |
| assert.ok(inspectedErr.includes(`info: { |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'syscall_test', |
| custom: 'custom' |
| },`)); |
| |
| err.syscall = 'custom_syscall'; |
| |
| inspectedErr = inspect(err); |
| |
| assert.ok(inspectedErr.includes(`info: { |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'custom_syscall', |
| custom: 'custom' |
| },`)); |
| } |
| |
| { |
| // toString should return the correct string |
| |
| const err = new ERR_TEST({ |
| code: 'ERR', |
| errno: 123, |
| message: 'something happened', |
| syscall: 'syscall_test', |
| }); |
| |
| assert.strictEqual( |
| err.toString(), |
| 'SystemError [ERR_TEST]: custom message: syscall_test returned ERR (something happened)' |
| ); |
| } |