diff options
-rw-r--r-- | doc/api/util.md | 20 | ||||
-rw-r--r-- | lib/child_process.js | 7 | ||||
-rw-r--r-- | lib/internal/util.js | 15 | ||||
-rw-r--r-- | lib/util.js | 12 | ||||
-rw-r--r-- | src/uv.cc | 2 | ||||
-rw-r--r-- | test/parallel/test-child-process-execfile.js | 5 | ||||
-rw-r--r-- | test/parallel/test-net-server-listen-handle.js | 7 | ||||
-rw-r--r-- | test/parallel/test-uv-errno.js | 59 | ||||
-rw-r--r-- | test/sequential/test-async-wrap-getasyncid.js | 3 |
9 files changed, 87 insertions, 43 deletions
diff --git a/doc/api/util.md b/doc/api/util.md index 68f8487b1b..c9ce952af3 100644 --- a/doc/api/util.md +++ b/doc/api/util.md @@ -257,6 +257,25 @@ intended as a debugging tool. Some input values can have a significant performance overhead that can block the event loop. Use this function with care and never in a hot code path. +## util.getSystemErrorName(err) +<!-- YAML +added: REPLACEME +--> + +* `err` {number} +* Returns: {string} + +Returns the string name for a numeric error code that comes from a Node.js API. +The mapping between error codes and error names is platform-dependent. +See [Common System Errors][] for the names of common errors. + +```js +fs.access('file/that/does/not/exist', (err) => { + const name = util.getSystemErrorName(err.errno); + console.error(name); // ENOENT +}); +``` + ## util.inherits(constructor, superConstructor) <!-- YAML added: v0.3.0 @@ -1362,6 +1381,7 @@ Deprecated predecessor of `console.log`. [Customizing `util.inspect` colors]: #util_customizing_util_inspect_colors [Internationalization]: intl.html [WHATWG Encoding Standard]: https://encoding.spec.whatwg.org/ +[Common System Errors]: errors.html#errors_common_system_errors [constructor]: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/constructor [list of deprecated APIS]: deprecations.html#deprecations_list_of_deprecated_apis [semantically incompatible]: https://github.com/nodejs/node/issues/4179 diff --git a/lib/child_process.js b/lib/child_process.js index 00d1bfc57d..b190d9c70a 100644 --- a/lib/child_process.js +++ b/lib/child_process.js @@ -22,7 +22,9 @@ 'use strict'; const util = require('util'); -const { deprecate, convertToValidSignal } = require('internal/util'); +const { + deprecate, convertToValidSignal, getSystemErrorName +} = require('internal/util'); const { isUint8Array } = require('internal/util/types'); const { createPromise, promiseResolve, promiseReject } = process.binding('util'); @@ -30,7 +32,6 @@ const debug = util.debuglog('child_process'); const { Buffer } = require('buffer'); const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap'); const errors = require('internal/errors'); -const { errname } = process.binding('uv'); const child_process = require('internal/child_process'); const { _validateStdio, @@ -275,7 +276,7 @@ exports.execFile = function(file /*, args, options, callback*/) { if (!ex) { ex = new Error('Command failed: ' + cmd + '\n' + stderr); ex.killed = child.killed || killed; - ex.code = code < 0 ? errname(code) : code; + ex.code = code < 0 ? getSystemErrorName(code) : code; ex.signal = signal; } diff --git a/lib/internal/util.js b/lib/internal/util.js index 2cce2be5bf..5b11bd6bf6 100644 --- a/lib/internal/util.js +++ b/lib/internal/util.js @@ -12,6 +12,7 @@ const { arrow_message_private_symbol: kArrowMessagePrivateSymbolIndex, decorated_private_symbol: kDecoratedPrivateSymbolIndex } = process.binding('util'); +const { errmap } = process.binding('uv'); const noCrypto = !process.versions.openssl; @@ -213,6 +214,19 @@ function getConstructorOf(obj) { return null; } +function getSystemErrorName(err) { + if (typeof err !== 'number') { + throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'err', 'number', err); + } + if (err >= 0 || !Number.isSafeInteger(err)) { + throw new errors.RangeError('ERR_OUT_OF_RANGE', 'err', + 'a negative integer', err); + } + + const entry = errmap.get(err); + return entry ? entry[0] : `Unknown system error ${err}`; +} + // getConstructorOf is wrapped into this to save iterations function getIdentificationOf(obj) { const original = obj; @@ -340,6 +354,7 @@ module.exports = { emitExperimentalWarning, filterDuplicateStrings, getConstructorOf, + getSystemErrorName, getIdentificationOf, isError, join, diff --git a/lib/util.js b/lib/util.js index 541577db08..dfa7502260 100644 --- a/lib/util.js +++ b/lib/util.js @@ -25,7 +25,6 @@ const errors = require('internal/errors'); const { TextDecoder, TextEncoder } = require('internal/encoding'); const { isBuffer } = require('buffer').Buffer; -const { errname } = process.binding('uv'); const { previewMapIterator, previewSetIterator } = require('internal/v8'); const { @@ -56,6 +55,7 @@ const { const { customInspectSymbol, deprecate, + getSystemErrorName, getIdentificationOf, isError, promisify, @@ -1055,14 +1055,7 @@ function error(...args) { } function _errnoException(err, syscall, original) { - if (typeof err !== 'number') { - throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'err', 'number', err); - } - if (err >= 0 || !Number.isSafeInteger(err)) { - throw new errors.RangeError('ERR_OUT_OF_RANGE', 'err', - 'a negative integer', err); - } - const name = errname(err); + const name = getSystemErrorName(err); var message = `${syscall} ${name}`; if (original) message += ` ${original}`; @@ -1151,6 +1144,7 @@ module.exports = exports = { debuglog, deprecate, format, + getSystemErrorName, inherits, inspect, isArray: Array.isArray, @@ -39,6 +39,8 @@ using v8::String; using v8::Value; +// TODO(joyeecheung): deprecate this function in favor of +// lib/util.getSystemErrorName() void ErrName(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); int err = args[0]->Int32Value(); diff --git a/test/parallel/test-child-process-execfile.js b/test/parallel/test-child-process-execfile.js index 62cc7f534d..415489e9db 100644 --- a/test/parallel/test-child-process-execfile.js +++ b/test/parallel/test-child-process-execfile.js @@ -1,8 +1,9 @@ 'use strict'; + const common = require('../common'); const assert = require('assert'); const execFile = require('child_process').execFile; -const uv = process.binding('uv'); +const { getSystemErrorName } = require('util'); const fixtures = require('../common/fixtures'); const fixture = fixtures.path('exit.js'); @@ -26,7 +27,7 @@ const fixture = fixtures.path('exit.js'); const code = -1; const callback = common.mustCall((err, stdout, stderr) => { assert.strictEqual(err.toString().trim(), errorString); - assert.strictEqual(err.code, uv.errname(code)); + assert.strictEqual(err.code, getSystemErrorName(code)); assert.strictEqual(err.killed, true); assert.strictEqual(err.signal, null); assert.strictEqual(err.cmd, process.execPath); diff --git a/test/parallel/test-net-server-listen-handle.js b/test/parallel/test-net-server-listen-handle.js index 2b56817d2c..06f03e304c 100644 --- a/test/parallel/test-net-server-listen-handle.js +++ b/test/parallel/test-net-server-listen-handle.js @@ -4,7 +4,7 @@ const common = require('../common'); const assert = require('assert'); const net = require('net'); const fs = require('fs'); -const uv = process.binding('uv'); +const { getSystemErrorName } = require('util'); const { TCP, constants: TCPConstants } = process.binding('tcp_wrap'); const { Pipe, constants: PipeConstants } = process.binding('pipe_wrap'); @@ -46,9 +46,10 @@ function randomHandle(type) { handleName = `pipe ${path}`; } - if (errno < 0) { // uv.errname requires err < 0 - assert(errno >= 0, `unable to bind ${handleName}: ${uv.errname(errno)}`); + if (errno < 0) { + assert.fail(`unable to bind ${handleName}: ${getSystemErrorName(errno)}`); } + if (!common.isWindows) { // fd doesn't work on windows // err >= 0 but fd = -1, should not happen assert.notStrictEqual(handle.fd, -1, diff --git a/test/parallel/test-uv-errno.js b/test/parallel/test-uv-errno.js index e4a40f20c8..8b10b52c00 100644 --- a/test/parallel/test-uv-errno.js +++ b/test/parallel/test-uv-errno.js @@ -2,9 +2,12 @@ const common = require('../common'); const assert = require('assert'); -const util = require('util'); -const uv = process.binding('uv'); +const { + getSystemErrorName, + _errnoException +} = require('util'); +const uv = process.binding('uv'); const keys = Object.keys(uv); keys.forEach((key) => { @@ -12,33 +15,39 @@ keys.forEach((key) => { return; assert.doesNotThrow(() => { - const err = util._errnoException(uv[key], 'test'); + const err = _errnoException(uv[key], 'test'); const name = uv.errname(uv[key]); - assert.strictEqual(err.code, err.errno); + assert.strictEqual(getSystemErrorName(uv[key]), name); assert.strictEqual(err.code, name); + assert.strictEqual(err.code, err.errno); assert.strictEqual(err.message, `test ${name}`); }); }); -['test', {}, []].forEach((key) => { - common.expectsError( - () => util._errnoException(key), - { - code: 'ERR_INVALID_ARG_TYPE', - type: TypeError, - message: 'The "err" argument must be of type number. ' + - `Received type ${typeof key}` - }); -}); +function runTest(fn) { + ['test', {}, []].forEach((err) => { + common.expectsError( + () => fn(err), + { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "err" argument must be of type number. ' + + `Received type ${typeof err}` + }); + }); -[0, 1, Infinity, -Infinity, NaN].forEach((key) => { - common.expectsError( - () => util._errnoException(key), - { - code: 'ERR_OUT_OF_RANGE', - type: RangeError, - message: 'The value of "err" is out of range. ' + - 'It must be a negative integer. ' + - `Received ${key}` - }); -}); + [0, 1, Infinity, -Infinity, NaN].forEach((err) => { + common.expectsError( + () => fn(err), + { + code: 'ERR_OUT_OF_RANGE', + type: RangeError, + message: 'The value of "err" is out of range. ' + + 'It must be a negative integer. ' + + `Received ${err}` + }); + }); +} + +runTest(_errnoException); +runTest(getSystemErrorName); diff --git a/test/sequential/test-async-wrap-getasyncid.js b/test/sequential/test-async-wrap-getasyncid.js index 1e04a90fd6..918e76ac49 100644 --- a/test/sequential/test-async-wrap-getasyncid.js +++ b/test/sequential/test-async-wrap-getasyncid.js @@ -6,6 +6,7 @@ const fs = require('fs'); const net = require('net'); const providers = Object.assign({}, process.binding('async_wrap').Providers); const fixtures = require('../common/fixtures'); +const { getSystemErrorName } = require('util'); // Make sure that all Providers are tested. { @@ -205,7 +206,7 @@ if (common.hasCrypto) { // eslint-disable-line crypto-check // Use a long string to make sure the write happens asynchronously. const err = handle.writeLatin1String(wreq, 'hi'.repeat(100000)); if (err) - throw new Error(`write failed: ${process.binding('uv').errname(err)}`); + throw new Error(`write failed: ${getSystemErrorName(err)}`); testInitialized(wreq, 'WriteWrap'); }); req.address = common.localhostIPv4; |