Skip to content

Commit

Permalink
errors: move error creation helpers to errors.js
Browse files Browse the repository at this point in the history
This commit moves error creation helpers scattered around
under lib/ into lib/internal/errors.js in the hope of being clearer
about the differences of errors that we throw into the user land.

- Move util._errnoException and util._exceptionWithHostPort
  into internal/errors.js and simplify their logic so it's
  clearer what the properties these helpers create.
- Move the errnoException helper in dns.js to internal/errors.js
  into internal/errors.js and rename it to dnsException. Simplify
  it's logic so it no longer calls errnoException and skips
  the unnecessary argument checks.

PR-URL: #18546
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
joyeecheung committed Feb 7, 2018
1 parent 0303848 commit c0762c2
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 92 deletions.
4 changes: 2 additions & 2 deletions lib/dgram.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ const SEND_BUFFER = false;
// Lazily loaded
var cluster = null;

const errnoException = util._errnoException;
const exceptionWithHostPort = util._exceptionWithHostPort;
const errnoException = errors.errnoException;
const exceptionWithHostPort = errors.exceptionWithHostPort;


function lookup4(lookup, address, callback) {
Expand Down
47 changes: 8 additions & 39 deletions lib/dns.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,10 @@

'use strict';

const util = require('util');

const cares = process.binding('cares_wrap');
const { isIP, isIPv4, isLegalPort } = require('internal/net');
const { customPromisifyArgs } = require('internal/util');
const errors = require('internal/errors');
const {
UV_EAI_MEMORY,
UV_EAI_NODATA,
UV_EAI_NONAME
} = process.binding('uv');

const {
GetAddrInfoReqWrap,
Expand All @@ -40,36 +33,12 @@ const {
ChannelWrap,
} = cares;

function errnoException(err, syscall, hostname) {
// FIXME(bnoordhuis) Remove this backwards compatibility nonsense and pass
// the true error to the user. ENOTFOUND is not even a proper POSIX error!
if (err === UV_EAI_MEMORY ||
err === UV_EAI_NODATA ||
err === UV_EAI_NONAME) {
err = 'ENOTFOUND';
}
var ex = null;
if (typeof err === 'string') { // c-ares error code.
const errHost = hostname ? ` ${hostname}` : '';
ex = new Error(`${syscall} ${err}${errHost}`);
ex.code = err;
ex.errno = err;
ex.syscall = syscall;
} else {
ex = util._errnoException(err, syscall);
}
if (hostname) {
ex.hostname = hostname;
}
return ex;
}

const IANA_DNS_PORT = 53;

const dnsException = errors.dnsException;

function onlookup(err, addresses) {
if (err) {
return this.callback(errnoException(err, 'getaddrinfo', this.hostname));
return this.callback(dnsException(err, 'getaddrinfo', this.hostname));
}
if (this.family) {
this.callback(null, addresses[0], this.family);
Expand All @@ -81,7 +50,7 @@ function onlookup(err, addresses) {

function onlookupall(err, addresses) {
if (err) {
return this.callback(errnoException(err, 'getaddrinfo', this.hostname));
return this.callback(dnsException(err, 'getaddrinfo', this.hostname));
}

var family = this.family;
Expand Down Expand Up @@ -161,7 +130,7 @@ function lookup(hostname, options, callback) {

var err = cares.getaddrinfo(req, hostname, family, hints, verbatim);
if (err) {
process.nextTick(callback, errnoException(err, 'getaddrinfo', hostname));
process.nextTick(callback, dnsException(err, 'getaddrinfo', hostname));
return {};
}
return req;
Expand All @@ -173,7 +142,7 @@ Object.defineProperty(lookup, customPromisifyArgs,

function onlookupservice(err, host, service) {
if (err)
return this.callback(errnoException(err, 'getnameinfo', this.host));
return this.callback(dnsException(err, 'getnameinfo', this.host));

this.callback(null, host, service);
}
Expand Down Expand Up @@ -202,7 +171,7 @@ function lookupService(host, port, callback) {
req.oncomplete = onlookupservice;

var err = cares.getnameinfo(req, host, port);
if (err) throw errnoException(err, 'getnameinfo', host);
if (err) throw dnsException(err, 'getnameinfo', host);
return req;
}

Expand All @@ -215,7 +184,7 @@ function onresolve(err, result, ttls) {
result = result.map((address, index) => ({ address, ttl: ttls[index] }));

if (err)
this.callback(errnoException(err, this.bindingName, this.hostname));
this.callback(dnsException(err, this.bindingName, this.hostname));
else
this.callback(null, result);
}
Expand Down Expand Up @@ -253,7 +222,7 @@ function resolver(bindingName) {
req.oncomplete = onresolve;
req.ttl = !!(options && options.ttl);
var err = this._handle[bindingName](req, name);
if (err) throw errnoException(err, bindingName);
if (err) throw dnsException(err, bindingName);
return req;
}
Object.defineProperty(query, 'name', { value: bindingName });
Expand Down
2 changes: 1 addition & 1 deletion lib/fs.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const { kMaxLength } = require('buffer');
const isWindows = process.platform === 'win32';

const DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
const errnoException = util._errnoException;
const errnoException = errors.errnoException;

let truncateWarn = true;

Expand Down
2 changes: 1 addition & 1 deletion lib/internal/child_process.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const {
UV_ESRCH
} = process.binding('uv');

const errnoException = util._errnoException;
const errnoException = errors.errnoException;
const { SocketListSend, SocketListReceive } = SocketList;

const MAX_HANDLE_RETRANSMISSIONS = 3;
Expand Down
131 changes: 126 additions & 5 deletions lib/internal/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ var green = '';
var red = '';
var white = '';

const { errmap } = process.binding('uv');
const {
errmap,
UV_EAI_MEMORY,
UV_EAI_NODATA,
UV_EAI_NONAME
} = process.binding('uv');
const { kMaxLength } = process.binding('buffer');
const { defineProperty } = Object;

Expand All @@ -33,6 +38,14 @@ function lazyUtil() {
return util_;
}

var internalUtil = null;
function lazyInternalUtil() {
if (!internalUtil) {
internalUtil = require('internal/util');
}
return internalUtil;
}

function makeNodeError(Base) {
return class NodeError extends Base {
constructor(key, ...args) {
Expand Down Expand Up @@ -356,10 +369,15 @@ function E(sym, val) {
messages.set(sym, typeof val === 'function' ? val : String(val));
}

// This creates an error compatible with errors produced in UVException
// using the context collected in CollectUVExceptionInfo
// The goal is to migrate them to ERR_* errors later when
// compatibility is not a concern
/**
* 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}
*/
function uvException(ctx) {
const err = new Error();

Expand Down Expand Up @@ -389,7 +407,110 @@ function uvException(ctx) {
return err;
}

/**
* This used to be util._errnoException().
*
* @param {number} err - A libuv error number
* @param {string} syscall
* @param {string} [original]
* @returns {Error}
*/
function errnoException(err, syscall, original) {
// TODO(joyeecheung): We have to use the type-checked
// getSystemErrorName(err) to guard against invalid arguments from users.
// This can be replaced with [ code ] = errmap.get(err) when this method
// is no longer exposed to user land.
const code = lazyUtil().getSystemErrorName(err);
const message = original ?
`${syscall} ${code} ${original}` : `${syscall} ${code}`;

const ex = new Error(message);
// TODO(joyeecheung): errno is supposed to err, like in uvException
ex.code = ex.errno = code;
ex.syscall = syscall;

Error.captureStackTrace(ex, errnoException);
return ex;
}

/**
* This used to be util._exceptionWithHostPort().
*
* @param {number} err - A libuv error number
* @param {string} syscall
* @param {string} address
* @param {number} [port]
* @param {string} [additional]
* @returns {Error}
*/
function exceptionWithHostPort(err, syscall, address, port, additional) {
// TODO(joyeecheung): We have to use the type-checked
// getSystemErrorName(err) to guard against invalid arguments from users.
// This can be replaced with [ code ] = errmap.get(err) when this method
// is no longer exposed to user land.
const code = lazyUtil().getSystemErrorName(err);
let details = '';
if (port && port > 0) {
details = ` ${address}:${port}`;
} else if (address) {
details = ` ${address}`;
}
if (additional) {
details += ` - Local (${additional})`;
}

const ex = new Error(`${syscall} ${code}${details}`);
// TODO(joyeecheung): errno is supposed to err, like in uvException
ex.code = ex.errno = code;
ex.syscall = syscall;
ex.address = address;
if (port) {
ex.port = port;
}

Error.captureStackTrace(ex, exceptionWithHostPort);
return ex;
}

/**
* @param {number|string} err - A libuv error number or a c-ares error code
* @param {string} syscall
* @param {string} [hostname]
* @returns {Error}
*/
function dnsException(err, syscall, hostname) {
const ex = new Error();
// FIXME(bnoordhuis) Remove this backwards compatibility nonsense and pass
// the true error to the user. ENOTFOUND is not even a proper POSIX error!
if (err === UV_EAI_MEMORY ||
err === UV_EAI_NODATA ||
err === UV_EAI_NONAME) {
err = 'ENOTFOUND'; // Fabricated error name.
}
if (typeof err === 'string') { // c-ares error code.
const errHost = hostname ? ` ${hostname}` : '';
ex.message = `${syscall} ${err}${errHost}`;
// TODO(joyeecheung): errno is supposed to be a number, like in uvException
ex.code = ex.errno = err;
ex.syscall = syscall;
} else { // libuv error number
const code = lazyInternalUtil().getSystemErrorName(err);
ex.message = `${syscall} ${code}`;
// TODO(joyeecheung): errno is supposed to be err, like in uvException
ex.code = ex.errno = code;
ex.syscall = syscall;
}
if (hostname) {
ex.hostname = hostname;
}
Error.captureStackTrace(ex, dnsException);
return ex;
}

module.exports = exports = {
dnsException,
errnoException,
exceptionWithHostPort,
uvException,
message,
Error: makeNodeError(Error),
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/http2/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -1631,7 +1631,7 @@ class Http2Stream extends Duplex {
req.async = false;
const err = createWriteReq(req, handle, data, encoding);
if (err)
throw util._errnoException(err, 'write', req.error);
throw errors.errnoException(err, 'write', req.error);
trackWriteState(this, req.bytes);
}

Expand Down Expand Up @@ -1674,7 +1674,7 @@ class Http2Stream extends Duplex {
}
const err = handle.writev(req, chunks);
if (err)
throw util._errnoException(err, 'write', req.error);
throw errors.errnoException(err, 'write', req.error);
trackWriteState(this, req.bytes);
}

Expand Down
4 changes: 2 additions & 2 deletions lib/internal/process.js
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ function setupKillAndExit() {
}

if (err)
throw util._errnoException(err, 'kill');
throw errors.errnoException(err, 'kill');

return true;
};
Expand Down Expand Up @@ -200,7 +200,7 @@ function setupSignalHandlers() {
const err = wrap.start(signum);
if (err) {
wrap.close();
throw util._errnoException(err, 'uv_signal_start');
throw errors.errnoException(err, 'uv_signal_start');
}

signalWraps[type] = wrap;
Expand Down
4 changes: 2 additions & 2 deletions lib/net.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ const kLastWriteQueueSize = Symbol('lastWriteQueueSize');
// reasons it's lazy loaded.
var cluster = null;

const errnoException = util._errnoException;
const exceptionWithHostPort = util._exceptionWithHostPort;
const errnoException = errors.errnoException;
const exceptionWithHostPort = errors.exceptionWithHostPort;

const {
kTimeout,
Expand Down
4 changes: 2 additions & 2 deletions lib/tty.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

'use strict';

const { inherits, _errnoException, _extend } = require('util');
const { inherits, _extend } = require('util');
const net = require('net');
const { TTY, isTTY } = process.binding('tty_wrap');
const errors = require('internal/errors');
Expand Down Expand Up @@ -178,7 +178,7 @@ WriteStream.prototype._refreshSize = function() {
const winSize = new Array(2);
const err = this._handle.getWindowSize(winSize);
if (err) {
this.emit('error', _errnoException(err, 'getWindowSize'));
this.emit('error', errors.errnoException(err, 'getWindowSize'));
return;
}
const [newCols, newRows] = winSize;
Expand Down
Loading

0 comments on commit c0762c2

Please sign in to comment.