Skip to content

Commit 58831b2

Browse files
committed
uv: improvements to process.binding('uv')
* ensure that UV_... props are constants * improve error message ... the error message when passing in `err >= 0` to `util._errnoException()` was less than useful. * refine uses of process.binding('uv') PR-URL: #14933 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Refael Ackermann <[email protected]> Reviewed-By: Colin Ihrig <[email protected]>
1 parent 5e7c697 commit 58831b2

10 files changed

+102
-39
lines changed

lib/_stream_wrap.js

+6-8
Original file line numberDiff line numberDiff line change
@@ -129,20 +129,18 @@ StreamWrap.prototype.doWrite = function doWrite(req, bufs) {
129129
// Ensure that this is called once in case of error
130130
pending = 0;
131131

132+
let errCode = 0;
133+
if (err) {
134+
const code = uv[`UV_${err.code}`];
135+
errCode = (err.code && code) ? code : uv.UV_EPIPE;
136+
}
137+
132138
// Ensure that write was dispatched
133139
setImmediate(function() {
134140
// Do not invoke callback twice
135141
if (!self._dequeue(item))
136142
return;
137143

138-
var errCode = 0;
139-
if (err) {
140-
if (err.code && uv['UV_' + err.code])
141-
errCode = uv['UV_' + err.code];
142-
else
143-
errCode = uv.UV_EPIPE;
144-
}
145-
146144
handle.doAfterWrite(req);
147145
handle.finishWrite(req, errCode);
148146
});

lib/child_process.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ const { createPromise,
2727
promiseResolve, promiseReject } = process.binding('util');
2828
const debug = util.debuglog('child_process');
2929

30-
const uv = process.binding('uv');
3130
const Buffer = require('buffer').Buffer;
3231
const Pipe = process.binding('pipe_wrap').Pipe;
3332
const { isUint8Array } = process.binding('util');
33+
const { errname } = process.binding('uv');
3434
const child_process = require('internal/child_process');
3535

3636
const _validateStdio = child_process._validateStdio;
@@ -267,7 +267,7 @@ exports.execFile = function(file /*, args, options, callback*/) {
267267
if (!ex) {
268268
ex = new Error('Command failed: ' + cmd + '\n' + stderr);
269269
ex.killed = child.killed || killed;
270-
ex.code = code < 0 ? uv.errname(code) : code;
270+
ex.code = code < 0 ? errname(code) : code;
271271
ex.signal = signal;
272272
}
273273

@@ -565,7 +565,7 @@ function checkExecSyncError(ret, args, cmd) {
565565
err = new Error(msg);
566566
}
567567
if (err) {
568-
err.status = ret.status < 0 ? uv.errname(ret.status) : ret.status;
568+
err.status = ret.status < 0 ? errname(ret.status) : ret.status;
569569
err.signal = ret.signal;
570570
}
571571
return err;

lib/dns.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,14 @@
2424
const util = require('util');
2525

2626
const cares = process.binding('cares_wrap');
27-
const uv = process.binding('uv');
2827
const internalNet = require('internal/net');
2928
const { customPromisifyArgs } = require('internal/util');
3029
const errors = require('internal/errors');
30+
const {
31+
UV_EAI_MEMORY,
32+
UV_EAI_NODATA,
33+
UV_EAI_NONAME
34+
} = process.binding('uv');
3135

3236
const {
3337
GetAddrInfoReqWrap,
@@ -43,9 +47,9 @@ const isLegalPort = internalNet.isLegalPort;
4347
function errnoException(err, syscall, hostname) {
4448
// FIXME(bnoordhuis) Remove this backwards compatibility nonsense and pass
4549
// the true error to the user. ENOTFOUND is not even a proper POSIX error!
46-
if (err === uv.UV_EAI_MEMORY ||
47-
err === uv.UV_EAI_NODATA ||
48-
err === uv.UV_EAI_NONAME) {
50+
if (err === UV_EAI_MEMORY ||
51+
err === UV_EAI_NODATA ||
52+
err === UV_EAI_NONAME) {
4953
err = 'ENOTFOUND';
5054
}
5155
var ex = null;

lib/internal/child_process.js

+17-8
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ const assert = require('assert');
1010

1111
const Process = process.binding('process_wrap').Process;
1212
const WriteWrap = process.binding('stream_wrap').WriteWrap;
13-
const uv = process.binding('uv');
1413
const Pipe = process.binding('pipe_wrap').Pipe;
1514
const TTY = process.binding('tty_wrap').TTY;
1615
const TCP = process.binding('tcp_wrap').TCP;
@@ -20,6 +19,16 @@ const { isUint8Array } = process.binding('util');
2019
const { convertToValidSignal } = require('internal/util');
2120
const spawn_sync = process.binding('spawn_sync');
2221

22+
const {
23+
UV_EAGAIN,
24+
UV_EINVAL,
25+
UV_EMFILE,
26+
UV_ENFILE,
27+
UV_ENOENT,
28+
UV_ENOSYS,
29+
UV_ESRCH
30+
} = process.binding('uv');
31+
2332
const errnoException = util._errnoException;
2433
const SocketListSend = SocketList.SocketListSend;
2534
const SocketListReceive = SocketList.SocketListReceive;
@@ -307,17 +316,17 @@ ChildProcess.prototype.spawn = function(options) {
307316
var err = this._handle.spawn(options);
308317

309318
// Run-time errors should emit an error, not throw an exception.
310-
if (err === uv.UV_EAGAIN ||
311-
err === uv.UV_EMFILE ||
312-
err === uv.UV_ENFILE ||
313-
err === uv.UV_ENOENT) {
319+
if (err === UV_EAGAIN ||
320+
err === UV_EMFILE ||
321+
err === UV_ENFILE ||
322+
err === UV_ENOENT) {
314323
process.nextTick(onErrorNT, this, err);
315324
// There is no point in continuing when we've hit EMFILE or ENFILE
316325
// because we won't be able to set up the stdio file descriptors.
317326
// It's kind of silly that the de facto spec for ENOENT (the test suite)
318327
// mandates that stdio _is_ set up, even if there is no process on the
319328
// receiving end, but it is what it is.
320-
if (err !== uv.UV_ENOENT) return err;
329+
if (err !== UV_ENOENT) return err;
321330
} else if (err) {
322331
// Close all opened fds on error
323332
for (i = 0; i < stdio.length; i++) {
@@ -394,9 +403,9 @@ ChildProcess.prototype.kill = function(sig) {
394403
this.killed = true;
395404
return true;
396405
}
397-
if (err === uv.UV_ESRCH) {
406+
if (err === UV_ESRCH) {
398407
/* Already dead. */
399-
} else if (err === uv.UV_EINVAL || err === uv.UV_ENOSYS) {
408+
} else if (err === UV_EINVAL || err === UV_ENOSYS) {
400409
/* The underlying platform doesn't support this signal. */
401410
throw errnoException(err, 'kill');
402411
} else {

lib/internal/cluster/round_robin_handle.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ RoundRobinHandle.prototype.add = function(worker, send) {
5656
// Hack: translate 'EADDRINUSE' error string back to numeric error code.
5757
// It works but ideally we'd have some backchannel between the net and
5858
// cluster modules for stuff like this.
59-
const errno = uv['UV_' + err.errno];
60-
send(errno, null);
59+
send(uv[`UV_${err.errno}`], null);
6160
});
6261
};
6362

lib/net.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ const internalUtil = require('internal/util');
2929
const internalNet = require('internal/net');
3030
const assert = require('assert');
3131
const cares = process.binding('cares_wrap');
32-
const uv = process.binding('uv');
32+
const {
33+
UV_EADDRINUSE,
34+
UV_EINVAL,
35+
UV_EOF
36+
} = process.binding('uv');
3337

3438
const Buffer = require('buffer').Buffer;
3539
const TTYWrap = process.binding('tty_wrap');
@@ -604,7 +608,7 @@ function onread(nread, buffer) {
604608
}
605609

606610
// Error, possibly EOF.
607-
if (nread !== uv.UV_EOF) {
611+
if (nread !== UV_EOF) {
608612
return self.destroy(errnoException(nread, 'read'));
609613
}
610614

@@ -1229,7 +1233,7 @@ function createServerHandle(address, port, addressType, fd) {
12291233
} catch (e) {
12301234
// Not a fd we can listen on. This will trigger an error.
12311235
debug('listen invalid fd=%d:', fd, e.message);
1232-
return uv.UV_EINVAL;
1236+
return UV_EINVAL;
12331237
}
12341238
handle.open(fd);
12351239
handle.readable = true;
@@ -1389,7 +1393,7 @@ function listenInCluster(server, address, port, addressType,
13891393
var out = {};
13901394
err = handle.getsockname(out);
13911395
if (err === 0 && port !== out.port)
1392-
err = uv.UV_EADDRINUSE;
1396+
err = UV_EADDRINUSE;
13931397
}
13941398

13951399
if (err) {

lib/util.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -1031,13 +1031,16 @@ function error(...args) {
10311031
}
10321032

10331033
function _errnoException(err, syscall, original) {
1034-
var name = errname(err);
1034+
if (typeof err !== 'number' || err >= 0 || !Number.isSafeInteger(err)) {
1035+
throw new errors.TypeError('ERR_INVALID_ARG_TYPE', 'err',
1036+
'negative number');
1037+
}
1038+
const name = errname(err);
10351039
var message = `${syscall} ${name}`;
10361040
if (original)
10371041
message += ` ${original}`;
1038-
var e = new Error(message);
1039-
e.code = name;
1040-
e.errno = name;
1042+
const e = new Error(message);
1043+
e.code = e.errno = name;
10411044
e.syscall = syscall;
10421045
return e;
10431046
}

src/uv.cc

+3-6
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ namespace {
2929

3030
using v8::Context;
3131
using v8::FunctionCallbackInfo;
32-
using v8::Integer;
3332
using v8::Local;
3433
using v8::Object;
3534
using v8::Value;
@@ -38,8 +37,7 @@ using v8::Value;
3837
void ErrName(const FunctionCallbackInfo<Value>& args) {
3938
Environment* env = Environment::GetCurrent(args);
4039
int err = args[0]->Int32Value();
41-
if (err >= 0)
42-
return env->ThrowError("err >= 0");
40+
CHECK_LT(err, 0);
4341
const char* name = uv_err_name(err);
4442
args.GetReturnValue().Set(OneByteString(env->isolate(), name));
4543
}
@@ -51,9 +49,8 @@ void InitializeUV(Local<Object> target,
5149
Environment* env = Environment::GetCurrent(context);
5250
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "errname"),
5351
env->NewFunctionTemplate(ErrName)->GetFunction());
54-
#define V(name, _) \
55-
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "UV_" # name), \
56-
Integer::New(env->isolate(), UV_ ## name));
52+
53+
#define V(name, _) NODE_DEFINE_CONSTANT(target, UV_##name);
5754
UV_ERRNO_MAP(V)
5855
#undef V
5956
}
+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
'use strict';
2+
3+
require('../common');
4+
const assert = require('assert');
5+
const uv = process.binding('uv');
6+
7+
// Ensures that the `UV_...` values in process.binding('uv')
8+
// are constants.
9+
10+
const keys = Object.keys(uv);
11+
keys.forEach((key) => {
12+
if (key === 'errname')
13+
return; // skip this
14+
const val = uv[key];
15+
assert.throws(() => uv[key] = 1,
16+
/^TypeError: Cannot assign to read only property/);
17+
assert.strictEqual(uv[key], val);
18+
});

test/parallel/test-uv-errno.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const assert = require('assert');
5+
const util = require('util');
6+
const uv = process.binding('uv');
7+
8+
const keys = Object.keys(uv);
9+
10+
keys.forEach((key) => {
11+
if (key === 'errname')
12+
return;
13+
14+
assert.doesNotThrow(() => {
15+
const err = util._errnoException(uv[key], 'test');
16+
const name = uv.errname(uv[key]);
17+
assert.strictEqual(err.code, err.errno);
18+
assert.strictEqual(err.code, name);
19+
assert.strictEqual(err.message, `test ${name}`);
20+
});
21+
});
22+
23+
[0, 1, 'test', {}, [], Infinity, -Infinity, NaN].forEach((key) => {
24+
common.expectsError(
25+
() => util._errnoException(key),
26+
{
27+
code: 'ERR_INVALID_ARG_TYPE',
28+
type: TypeError,
29+
message: 'The "err" argument must be of type negative number'
30+
});
31+
});

0 commit comments

Comments
 (0)