summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoyee Cheung <joyeec9h3@gmail.com>2018-01-17 03:21:16 +0800
committerJoyee Cheung <joyeec9h3@gmail.com>2018-01-20 08:51:47 +0800
commit4af1bba6d0f1da1b4d444ef3a936e2ef2c639a1e (patch)
treeae8a75b9ac85984da88ee4af569215b94befd1b5
parentcbd634947d3aa308266ac6192a5af0a30445a449 (diff)
downloadandroid-node-v8-4af1bba6d0f1da1b4d444ef3a936e2ef2c639a1e.tar.gz
android-node-v8-4af1bba6d0f1da1b4d444ef3a936e2ef2c639a1e.tar.bz2
android-node-v8-4af1bba6d0f1da1b4d444ef3a936e2ef2c639a1e.zip
util: implement util.getSystemErrorName()
Reimplement uv.errname() as internal/util.getSystemErrorName() to avoid the memory leaks caused by unknown error codes and avoid calling into C++ for the error names. Also expose it as a public API for external use. PR-URL: https://github.com/nodejs/node/pull/18186 Refs: http://docs.libuv.org/en/v1.x/errors.html#c.uv_err_name Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
-rw-r--r--doc/api/util.md20
-rw-r--r--lib/child_process.js7
-rw-r--r--lib/internal/util.js15
-rw-r--r--lib/util.js12
-rw-r--r--src/uv.cc2
-rw-r--r--test/parallel/test-child-process-execfile.js5
-rw-r--r--test/parallel/test-net-server-listen-handle.js7
-rw-r--r--test/parallel/test-uv-errno.js59
-rw-r--r--test/sequential/test-async-wrap-getasyncid.js3
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,
diff --git a/src/uv.cc b/src/uv.cc
index 3c115cf05b..1ffd093c6b 100644
--- a/src/uv.cc
+++ b/src/uv.cc
@@ -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;