errors.js 3.32 KB
Newer Older
huahua committed
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 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
'use strict'
const { inspect } = require('util')

// adapted from node's internal/errors
// https://github.com/nodejs/node/blob/c8a04049/lib/internal/errors.js

// close copy of node's internal SystemError class.
class SystemError {
  constructor (code, prefix, context) {
    // XXX context.code is undefined in all constructors used in cp/polyfill
    // that may be a bug copied from node, maybe the constructor should use
    // `code` not `errno`?  nodejs/node#41104
    let message = `${prefix}: ${context.syscall} returned ` +
                  `${context.code} (${context.message})`

    if (context.path !== undefined) {
      message += ` ${context.path}`
    }
    if (context.dest !== undefined) {
      message += ` => ${context.dest}`
    }

    this.code = code
    Object.defineProperties(this, {
      name: {
        value: 'SystemError',
        enumerable: false,
        writable: true,
        configurable: true,
      },
      message: {
        value: message,
        enumerable: false,
        writable: true,
        configurable: true,
      },
      info: {
        value: context,
        enumerable: true,
        configurable: true,
        writable: false,
      },
      errno: {
        get () {
          return context.errno
        },
        set (value) {
          context.errno = value
        },
        enumerable: true,
        configurable: true,
      },
      syscall: {
        get () {
          return context.syscall
        },
        set (value) {
          context.syscall = value
        },
        enumerable: true,
        configurable: true,
      },
    })

    if (context.path !== undefined) {
      Object.defineProperty(this, 'path', {
        get () {
          return context.path
        },
        set (value) {
          context.path = value
        },
        enumerable: true,
        configurable: true,
      })
    }

    if (context.dest !== undefined) {
      Object.defineProperty(this, 'dest', {
        get () {
          return context.dest
        },
        set (value) {
          context.dest = value
        },
        enumerable: true,
        configurable: true,
      })
    }
  }

  toString () {
    return `${this.name} [${this.code}]: ${this.message}`
  }

  [Symbol.for('nodejs.util.inspect.custom')] (_recurseTimes, ctx) {
    return inspect(this, {
      ...ctx,
      getters: true,
      customInspect: false,
    })
  }
}

function E (code, message) {
  module.exports[code] = class NodeError extends SystemError {
    constructor (ctx) {
      super(code, message, ctx)
    }
  }
}

E('ERR_FS_CP_DIR_TO_NON_DIR', 'Cannot overwrite directory with non-directory')
E('ERR_FS_CP_EEXIST', 'Target already exists')
E('ERR_FS_CP_EINVAL', 'Invalid src or dest')
E('ERR_FS_CP_FIFO_PIPE', 'Cannot copy a FIFO pipe')
E('ERR_FS_CP_NON_DIR_TO_DIR', 'Cannot overwrite non-directory with directory')
E('ERR_FS_CP_SOCKET', 'Cannot copy a socket file')
E('ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY', 'Cannot overwrite symlink in subdirectory of self')
E('ERR_FS_CP_UNKNOWN', 'Cannot copy an unknown file type')
E('ERR_FS_EISDIR', 'Path is a directory')

module.exports.ERR_INVALID_ARG_TYPE = class ERR_INVALID_ARG_TYPE extends Error {
  constructor (name, expected, actual) {
    super()
    this.code = 'ERR_INVALID_ARG_TYPE'
    this.message = `The ${name} argument must be ${expected}. Received ${typeof actual}`
  }
}