code: function uvException(ctx) {
    const [ code, uvmsg ] = errmap.get(ctx.errno);
    let message = `${code}: ${uvmsg}, ${ctx.syscall}`;
  
    let path;
    let dest;
    if (ctx.path) {
      path = ctx.path.toString();
      message += ` '${path}'`;
    }
    if (ctx.dest) {
      dest = ctx.dest.toString();
      message += ` -> '${dest}'`;
    }
  
    // Pass the message to the constructor instead of setting it on the object
    // to make sure it is the same as the one created in C++
    // eslint-disable-next-line no-restricted-syntax
    const err = new Error(message);
  
    for (const prop of Object.keys(ctx)) {
      if (prop === 'message' || prop === 'path' || prop === 'dest') {
        continue;
      }
      err[prop] = ctx[prop];
    }
  
    err.code = code;
    if (path) {
      err.path = path;
    }
    if (dest) {
      err.dest = dest;
    }
  
    Error.captureStackTrace(err, uvException);
    return err;
  }
docs: This creates an error compatible with errors produced in the C++
  function UVException using a context object with data assembled in C++.
  The goal is to migrate them to ERR_* errors later when compatibility is
  not a concern.
  
  @param {Object} ctx
  @returns {Error}