All files / src/error utility.js

100% Statements 63/63
81.25% Branches 13/16
100% Functions 1/1
100% Lines 63/63

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 761x   1x   1x 1x   1x   1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 24x   24x 24x 11x 11x 13x   13x 24x   24x 24x 24x 24x 24x 24x 24x 24x   24x   24x 24x 24x 24x 24x 24x 11x 24x 24x   1x   1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x   1x  
// @ts-check
 
import { getPrototypeOf, getOwnPropertyDescriptors } from '../utility';
 
import { isFunction, isString } from '../base';
import { isError } from './index';
 
// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
 
/**
 * @param {any} [value]
 *  An optionally passed value of any type.
 * @returns {boolean}
 *  whether the passed value along its (non/existing) prototype chain
 *  does feature a prototype object which does qualify as the plain
 *  `Error` type's prototype.
 * @category Error Type Detection Helper
 */
export function hasMatchingErrorPrototype(value) {
  const prototype = getPrototypeOf(value) ?? null;
 
  // guard.
  if (prototype === null) {
    return false;
  }
  /* eslint-disable jsdoc/no-undefined-types */
 
  /** @type {PropertyDescriptor | Object} */
  const descriptors = getOwnPropertyDescriptors(prototype) ?? {};
 
  /** @type {PropertyDescriptor | null} */
  const constrDesc = descriptors.constructor ?? null;
  /** @type {PropertyDescriptor | null} */
  const messageDesc = descriptors.message ?? null;
  /** @type {PropertyDescriptor | null} */
  const nameDesc = descriptors.name ?? null;
  /** @type {PropertyDescriptor | null} */
  const toStringDesc = descriptors.toString ?? null;
 
  /* eslint-enable jsdoc/no-undefined-types */
 
  return (
    (isFunction(constrDesc?.value) &&
      isString(messageDesc?.value) &&
      isString(nameDesc?.value) &&
      isFunction(toStringDesc?.value) &&
      prototype.toString().split(':')[0].trim().slice(-5) === 'Error') ||
    isError(prototype)
  );
}
 
// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----
 
// /**
//  * Reaches for an error's stringified version by making
//  * use of ...
//  *
//  * ```
//  * Error.prototype.toString.call(value);
//  * ```
//  *
//  * ... which forces the error-specific `toString` default
//  * being executed upon the value it has been delegated to.
//  * @param {Function} value
//  *  Assumes and works best with an error
//  *  type but does not check for it.
//  * @returns {string}
//  *  Returns a stringified error signature.
//  * @category Error Type Detection Helper
//  */
// export function getErrorString(value) {
//   return Error.prototype.toString.call(value).trim();
// }
 
// ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- -----