| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 |
- 'use strict'
- const { format, inspect } = require('./util/inspect')
- const { AggregateError: CustomAggregateError } = require('./primordials')
- /*
- This file is a reduced and adapted version of the main lib/internal/errors.js file defined at
- https://github.com/nodejs/node/blob/main/lib/internal/errors.js
- Don't try to replace with the original file and keep it up to date (starting from E(...) definitions)
- with the upstream file.
- */
- const AggregateError = globalThis.AggregateError || CustomAggregateError
- const kIsNodeError = Symbol('kIsNodeError')
- const kTypes = [
- 'string',
- 'function',
- 'number',
- 'object',
- // Accept 'Function' and 'Object' as alternative to the lower cased version.
- 'Function',
- 'Object',
- 'boolean',
- 'bigint',
- 'symbol'
- ]
- const classRegExp = /^([A-Z][a-z0-9]*)+$/
- const nodeInternalPrefix = '__node_internal_'
- const codes = {}
- function assert(value, message) {
- if (!value) {
- throw new codes.ERR_INTERNAL_ASSERTION(message)
- }
- }
- // Only use this for integers! Decimal numbers do not work with this function.
- function addNumericalSeparator(val) {
- let res = ''
- let i = val.length
- const start = val[0] === '-' ? 1 : 0
- for (; i >= start + 4; i -= 3) {
- res = `_${val.slice(i - 3, i)}${res}`
- }
- return `${val.slice(0, i)}${res}`
- }
- function getMessage(key, msg, args) {
- if (typeof msg === 'function') {
- assert(
- msg.length <= args.length,
- // Default options do not count.
- `Code: ${key}; The provided arguments length (${args.length}) does not match the required ones (${msg.length}).`
- )
- return msg(...args)
- }
- const expectedLength = (msg.match(/%[dfijoOs]/g) || []).length
- assert(
- expectedLength === args.length,
- `Code: ${key}; The provided arguments length (${args.length}) does not match the required ones (${expectedLength}).`
- )
- if (args.length === 0) {
- return msg
- }
- return format(msg, ...args)
- }
- function E(code, message, Base) {
- if (!Base) {
- Base = Error
- }
- class NodeError extends Base {
- constructor(...args) {
- super(getMessage(code, message, args))
- }
- toString() {
- return `${this.name} [${code}]: ${this.message}`
- }
- }
- Object.defineProperties(NodeError.prototype, {
- name: {
- value: Base.name,
- writable: true,
- enumerable: false,
- configurable: true
- },
- toString: {
- value() {
- return `${this.name} [${code}]: ${this.message}`
- },
- writable: true,
- enumerable: false,
- configurable: true
- }
- })
- NodeError.prototype.code = code
- NodeError.prototype[kIsNodeError] = true
- codes[code] = NodeError
- }
- function hideStackFrames(fn) {
- // We rename the functions that will be hidden to cut off the stacktrace
- // at the outermost one
- const hidden = nodeInternalPrefix + fn.name
- Object.defineProperty(fn, 'name', {
- value: hidden
- })
- return fn
- }
- function aggregateTwoErrors(innerError, outerError) {
- if (innerError && outerError && innerError !== outerError) {
- if (Array.isArray(outerError.errors)) {
- // If `outerError` is already an `AggregateError`.
- outerError.errors.push(innerError)
- return outerError
- }
- const err = new AggregateError([outerError, innerError], outerError.message)
- err.code = outerError.code
- return err
- }
- return innerError || outerError
- }
- class AbortError extends Error {
- constructor(message = 'The operation was aborted', options = undefined) {
- if (options !== undefined && typeof options !== 'object') {
- throw new codes.ERR_INVALID_ARG_TYPE('options', 'Object', options)
- }
- super(message, options)
- this.code = 'ABORT_ERR'
- this.name = 'AbortError'
- }
- }
- E('ERR_ASSERTION', '%s', Error)
- E(
- 'ERR_INVALID_ARG_TYPE',
- (name, expected, actual) => {
- assert(typeof name === 'string', "'name' must be a string")
- if (!Array.isArray(expected)) {
- expected = [expected]
- }
- let msg = 'The '
- if (name.endsWith(' argument')) {
- // For cases like 'first argument'
- msg += `${name} `
- } else {
- msg += `"${name}" ${name.includes('.') ? 'property' : 'argument'} `
- }
- msg += 'must be '
- const types = []
- const instances = []
- const other = []
- for (const value of expected) {
- assert(typeof value === 'string', 'All expected entries have to be of type string')
- if (kTypes.includes(value)) {
- types.push(value.toLowerCase())
- } else if (classRegExp.test(value)) {
- instances.push(value)
- } else {
- assert(value !== 'object', 'The value "object" should be written as "Object"')
- other.push(value)
- }
- }
- // Special handle `object` in case other instances are allowed to outline
- // the differences between each other.
- if (instances.length > 0) {
- const pos = types.indexOf('object')
- if (pos !== -1) {
- types.splice(types, pos, 1)
- instances.push('Object')
- }
- }
- if (types.length > 0) {
- switch (types.length) {
- case 1:
- msg += `of type ${types[0]}`
- break
- case 2:
- msg += `one of type ${types[0]} or ${types[1]}`
- break
- default: {
- const last = types.pop()
- msg += `one of type ${types.join(', ')}, or ${last}`
- }
- }
- if (instances.length > 0 || other.length > 0) {
- msg += ' or '
- }
- }
- if (instances.length > 0) {
- switch (instances.length) {
- case 1:
- msg += `an instance of ${instances[0]}`
- break
- case 2:
- msg += `an instance of ${instances[0]} or ${instances[1]}`
- break
- default: {
- const last = instances.pop()
- msg += `an instance of ${instances.join(', ')}, or ${last}`
- }
- }
- if (other.length > 0) {
- msg += ' or '
- }
- }
- switch (other.length) {
- case 0:
- break
- case 1:
- if (other[0].toLowerCase() !== other[0]) {
- msg += 'an '
- }
- msg += `${other[0]}`
- break
- case 2:
- msg += `one of ${other[0]} or ${other[1]}`
- break
- default: {
- const last = other.pop()
- msg += `one of ${other.join(', ')}, or ${last}`
- }
- }
- if (actual == null) {
- msg += `. Received ${actual}`
- } else if (typeof actual === 'function' && actual.name) {
- msg += `. Received function ${actual.name}`
- } else if (typeof actual === 'object') {
- var _actual$constructor
- if (
- (_actual$constructor = actual.constructor) !== null &&
- _actual$constructor !== undefined &&
- _actual$constructor.name
- ) {
- msg += `. Received an instance of ${actual.constructor.name}`
- } else {
- const inspected = inspect(actual, {
- depth: -1
- })
- msg += `. Received ${inspected}`
- }
- } else {
- let inspected = inspect(actual, {
- colors: false
- })
- if (inspected.length > 25) {
- inspected = `${inspected.slice(0, 25)}...`
- }
- msg += `. Received type ${typeof actual} (${inspected})`
- }
- return msg
- },
- TypeError
- )
- E(
- 'ERR_INVALID_ARG_VALUE',
- (name, value, reason = 'is invalid') => {
- let inspected = inspect(value)
- if (inspected.length > 128) {
- inspected = inspected.slice(0, 128) + '...'
- }
- const type = name.includes('.') ? 'property' : 'argument'
- return `The ${type} '${name}' ${reason}. Received ${inspected}`
- },
- TypeError
- )
- E(
- 'ERR_INVALID_RETURN_VALUE',
- (input, name, value) => {
- var _value$constructor
- const type =
- value !== null &&
- value !== undefined &&
- (_value$constructor = value.constructor) !== null &&
- _value$constructor !== undefined &&
- _value$constructor.name
- ? `instance of ${value.constructor.name}`
- : `type ${typeof value}`
- return `Expected ${input} to be returned from the "${name}"` + ` function but got ${type}.`
- },
- TypeError
- )
- E(
- 'ERR_MISSING_ARGS',
- (...args) => {
- assert(args.length > 0, 'At least one arg needs to be specified')
- let msg
- const len = args.length
- args = (Array.isArray(args) ? args : [args]).map((a) => `"${a}"`).join(' or ')
- switch (len) {
- case 1:
- msg += `The ${args[0]} argument`
- break
- case 2:
- msg += `The ${args[0]} and ${args[1]} arguments`
- break
- default:
- {
- const last = args.pop()
- msg += `The ${args.join(', ')}, and ${last} arguments`
- }
- break
- }
- return `${msg} must be specified`
- },
- TypeError
- )
- E(
- 'ERR_OUT_OF_RANGE',
- (str, range, input) => {
- assert(range, 'Missing "range" argument')
- let received
- if (Number.isInteger(input) && Math.abs(input) > 2 ** 32) {
- received = addNumericalSeparator(String(input))
- } else if (typeof input === 'bigint') {
- received = String(input)
- const limit = BigInt(2) ** BigInt(32)
- if (input > limit || input < -limit) {
- received = addNumericalSeparator(received)
- }
- received += 'n'
- } else {
- received = inspect(input)
- }
- return `The value of "${str}" is out of range. It must be ${range}. Received ${received}`
- },
- RangeError
- )
- E('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times', Error)
- E('ERR_METHOD_NOT_IMPLEMENTED', 'The %s method is not implemented', Error)
- E('ERR_STREAM_ALREADY_FINISHED', 'Cannot call %s after a stream was finished', Error)
- E('ERR_STREAM_CANNOT_PIPE', 'Cannot pipe, not readable', Error)
- E('ERR_STREAM_DESTROYED', 'Cannot call %s after a stream was destroyed', Error)
- E('ERR_STREAM_NULL_VALUES', 'May not write null values to stream', TypeError)
- E('ERR_STREAM_PREMATURE_CLOSE', 'Premature close', Error)
- E('ERR_STREAM_PUSH_AFTER_EOF', 'stream.push() after EOF', Error)
- E('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event', Error)
- E('ERR_STREAM_WRITE_AFTER_END', 'write after end', Error)
- E('ERR_UNKNOWN_ENCODING', 'Unknown encoding: %s', TypeError)
- module.exports = {
- AbortError,
- aggregateTwoErrors: hideStackFrames(aggregateTwoErrors),
- hideStackFrames,
- codes
- }
|