From acc328ef5884ab55538c3953caea144b3f00e07a Mon Sep 17 00:00:00 2001 From: Rich Trott Date: Wed, 4 Apr 2018 10:57:44 -0700 Subject: [PATCH 01/12] doc: move mafintosh to Collaborators MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit mafintosh was accidentally added to the TSC list rather than the Collaborators list. This corrects that. PR-URL: https://github.com/nodejs/node/pull/19806 Reviewed-By: Anna Henningsen Reviewed-By: Ruben Bridgewater Reviewed-By: Michaël Zasso --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index f46b6f72e8b..42d34930892 100644 --- a/README.md +++ b/README.md @@ -252,8 +252,6 @@ For more information about the governance of the Node.js project, see **James M Snell** <jasnell@gmail.com> (he/him) * [joyeecheung](https://github.com/joyeecheung) - **Joyee Cheung** <joyeec9h3@gmail.com> (she/her) -* [mafintosh](https://github.com/mafintosh) -**Mathias Buus** <mathiasbuus@gmail.com> (he/him) * [mcollina](https://github.com/mcollina) - **Matteo Collina** <matteo.collina@gmail.com> (he/him) * [mhdawson](https://github.com/mhdawson) - @@ -422,6 +420,8 @@ For more information about the governance of the Node.js project, see **Luca Maraschi** <luca.maraschi@gmail.com> (he/him) * [maclover7](https://github.com/maclover7) - **Jon Moss** <me@jonathanmoss.me> (he/him) +* [mafintosh](https://github.com/mafintosh) +**Mathias Buus** <mathiasbuus@gmail.com> (he/him) * [mcollina](https://github.com/mcollina) - **Matteo Collina** <matteo.collina@gmail.com> (he/him) * [mhdawson](https://github.com/mhdawson) - From 3e0d40d4af6f437ecacb8b54d0d84ed0e5a4899f Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Wed, 21 Mar 2018 01:19:05 +0800 Subject: [PATCH 02/12] test: add info option to common.expectsError MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/19514 Reviewed-By: Michaël Zasso Reviewed-By: James M Snell --- test/common/README.md | 2 ++ test/common/index.js | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/test/common/README.md b/test/common/README.md index 765ebe01231..981e27a26b2 100644 --- a/test/common/README.md +++ b/test/common/README.md @@ -86,6 +86,8 @@ Indicates if there is more than 1gb of total memory. regular expression must match the `message` property of the expected error. * `name` [<string>] expected error must have this value for its `name` property. + * `info` <Object> expected error must have the same `info` property + that is deeply equal to this value. * `generatedMessage` [<string>] (`AssertionError` only) expected error must have this value for its `generatedMessage` property. diff --git a/test/common/index.js b/test/common/index.js index 4c4f0342f2f..ba53065ef01 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -704,6 +704,9 @@ exports.expectsError = function expectsError(fn, settings, exact) { } assert.strictEqual(typeName, type.name); } + if ('info' in settings) { + assert.deepStrictEqual(error.info, settings.info); + } if ('message' in settings) { const message = settings.message; if (typeof message === 'string') { @@ -717,7 +720,7 @@ exports.expectsError = function expectsError(fn, settings, exact) { // Check all error properties. const keys = Object.keys(settings); for (const key of keys) { - if (key === 'message' || key === 'type') + if (key === 'message' || key === 'type' || key === 'info') continue; const actual = error[key]; const expected = settings[key]; From 7d06761f839bbff8c671b0e1a6d541faa5452354 Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Wed, 21 Mar 2018 00:46:30 +0800 Subject: [PATCH 03/12] errors: improve SystemError messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit improves the SystemError messages by allowing user to combine a custom message and the libuv error message. Also since we now prefer use subclasses to construct the errors instead of using `new errors.SystemError()` directly, this removes the behavior of assigning a default error code `ERR_SYSTEM_ERROR` to SystemError and requires the user to directly use the `ERR_SYSTEM_ERROR` class to construct errors instead. Also merges `makeNodeError` into the SystemError class definition since that's the only place the function gets used and it seems unnecessary to introduce another level of inheritance. SystemError now directly inherits from Error instead of an intermmediate Error class that inherits from Error. Class hierarchy before this patch: ERR_SOCKET_BUFFER_SIZE -> Error (use message formatted by SystemError) ERR_SYSTEM_ERROR -> NodeError (temp) -> Error After: ERR_SOCKET_BUFFER_SIZE -> SystemError -> Error ERR_TTY_INIT_FAILED -> SystemError -> Error ERR_SYSTEM_ERROR -> SystemError -> Error Error messages before this patch: ``` const dgram = require('dgram'); const socket = dgram.createSocket('udp4'); socket.setRecvBufferSize(8192); // Error [ERR_SOCKET_BUFFER_SIZE]: Could not get or set buffer // size: Error [ERR_SYSTEM_ERROR]: bad file descriptor: // EBADF [uv_recv_buffer_size] // at bufferSize (dgram.js:191:11) // at Socket.setRecvBufferSize (dgram.js:689:3) const tty = require('tty'); new tty.WriteStream(1 << 30); // Error [ERR_SYSTEM_ERROR]: invalid argument: EINVAL [uv_tty_init] // at new WriteStream (tty.js:84:11) ``` After: ``` const dgram = require('dgram'); const socket = dgram.createSocket('udp4'); socket.setRecvBufferSize(8192); // SystemError [ERR_SOCKET_BUFFER_SIZE]: Could not get or set buffer // size: uv_recv_buffer_size returned EBADF (bad file descriptor) // at bufferSize (dgram.js:191:11) // at Socket.setRecvBufferSize (dgram.js:689:3) const tty = require('tty'); new tty.WriteStream(1 << 30); // SystemError [ERR_TTY_INIT_FAILED]: TTY initialization failed: // uv_tty_init returned EINVAL (invalid argument) // at new WriteStream (tty.js:84:11) ``` PR-URL: https://github.com/nodejs/node/pull/19514 Reviewed-By: Michaël Zasso Reviewed-By: James M Snell --- doc/api/errors.md | 5 + lib/dgram.js | 2 +- lib/internal/errors.js | 231 +++++++++--------- lib/os.js | 4 +- lib/tty.js | 6 +- .../parallel/test-dgram-socket-buffer-size.js | 88 +++++-- test/parallel/test-errors-systemerror.js | 160 ++++-------- test/parallel/test-ttywrap-invalid-fd.js | 24 +- 8 files changed, 259 insertions(+), 261 deletions(-) diff --git a/doc/api/errors.md b/doc/api/errors.md index 6e37ef50c35..936b1b0cd5d 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1521,6 +1521,11 @@ A Transform stream finished while it was still transforming. A Transform stream finished with data still in the write buffer. + +### ERR_TTY_INIT_FAILED + +The initialization of a TTY failed due to a system error. + ### ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET diff --git a/lib/dgram.js b/lib/dgram.js index fcf9f00a105..0a72834873e 100644 --- a/lib/dgram.js +++ b/lib/dgram.js @@ -188,7 +188,7 @@ function bufferSize(self, size, buffer) { const ctx = {}; const ret = self._handle.bufferSize(size, buffer, ctx); if (ret === undefined) { - throw new ERR_SOCKET_BUFFER_SIZE(new errors.SystemError(ctx)); + throw new ERR_SOCKET_BUFFER_SIZE(ctx); } return ret; } diff --git a/lib/internal/errors.js b/lib/internal/errors.js index f8073d15fe8..17b6f966d42 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -47,42 +47,112 @@ function inspectValue(val) { ).split('\n'); } -function makeNodeError(Base) { - return class NodeError extends Base { - constructor(key, ...args) { - super(message(key, args)); - defineProperty(this, kCode, { - configurable: true, - enumerable: false, - value: key, - writable: true - }); - } +function sysErrorMessage(prefix, ctx) { + let message = `${prefix}: ${ctx.syscall} returned ` + + `${ctx.code} (${ctx.message})`; + if (ctx.path !== undefined) + message += ` ${ctx.path}`; + if (ctx.dest !== undefined) + message += ` => ${ctx.dest}`; + return message; +} - get name() { - return `${super.name} [${this[kCode]}]`; - } +// A specialized Error that includes an additional info property with +// additional information about the error condition. +// It has the properties present in a UVException but with a custom error +// message followed by the uv error code and uv error message. +// It also has its own error code with the original uv error context put into +// `err.info`. +// The context passed into this error must have .code, .syscall and .message, +// and may have .path and .dest. +class SystemError extends Error { + constructor(key, context = {}) { + context = context || {}; + super(sysErrorMessage(message(key), context)); + Object.defineProperty(this, kInfo, { + configurable: false, + enumerable: false, + value: context + }); + Object.defineProperty(this, kCode, { + configurable: true, + enumerable: false, + value: key, + writable: true + }); + } - set name(value) { - defineProperty(this, 'name', { - configurable: true, - enumerable: true, - value, - writable: true - }); - } + get name() { + return `SystemError [${this[kCode]}]`; + } - get code() { - return this[kCode]; - } + set name(value) { + defineProperty(this, 'name', { + configurable: true, + enumerable: true, + value, + writable: true + }); + } - set code(value) { - defineProperty(this, 'code', { - configurable: true, - enumerable: true, - value, - writable: true - }); + get code() { + return this[kCode]; + } + + set code(value) { + defineProperty(this, 'code', { + configurable: true, + enumerable: true, + value, + writable: true + }); + } + + get info() { + return this[kInfo]; + } + + get errno() { + return this[kInfo].errno; + } + + set errno(val) { + this[kInfo].errno = val; + } + + get syscall() { + return this[kInfo].syscall; + } + + set syscall(val) { + this[kInfo].syscall = val; + } + + get path() { + return this[kInfo].path !== undefined ? + this[kInfo].path.toString() : undefined; + } + + set path(val) { + this[kInfo].path = val ? + lazyBuffer().from(val.toString()) : undefined; + } + + get dest() { + return this[kInfo].path !== undefined ? + this[kInfo].dest.toString() : undefined; + } + + set dest(val) { + this[kInfo].dest = val ? + lazyBuffer().from(val.toString()) : undefined; + } +} + +function makeSystemErrorWithCode(key) { + return class NodeError extends SystemError { + constructor(...args) { + super(key, ...args); } }; } @@ -124,8 +194,15 @@ function makeNodeErrorWithCode(Base, key) { // Utility function for registering the error codes. Only used here. Exported // *only* to allow for testing. function E(sym, val, def, ...otherClasses) { + // Special case for SystemError that formats the error message differently + // The SystemErrors only have SystemError as their base classes. messages.set(sym, val); - def = makeNodeErrorWithCode(def, sym); + if (def === SystemError) { + def = makeSystemErrorWithCode(sym); + } else { + def = makeNodeErrorWithCode(def, sym); + } + if (otherClasses.length !== 0) { otherClasses.forEach((clazz) => { def[clazz.name] = makeNodeErrorWithCode(clazz, sym); @@ -140,70 +217,6 @@ function lazyBuffer() { return buffer; } -// A specialized Error that includes an additional info property with -// additional information about the error condition. The code key will -// be extracted from the context object or the ERR_SYSTEM_ERROR default -// will be used. -class SystemError extends makeNodeError(Error) { - constructor(context) { - context = context || {}; - let code = 'ERR_SYSTEM_ERROR'; - if (messages.has(context.code)) - code = context.code; - super(code, - context.code, - context.syscall, - context.path, - context.dest, - context.message); - Object.defineProperty(this, kInfo, { - configurable: false, - enumerable: false, - value: context - }); - } - - get info() { - return this[kInfo]; - } - - get errno() { - return this[kInfo].errno; - } - - set errno(val) { - this[kInfo].errno = val; - } - - get syscall() { - return this[kInfo].syscall; - } - - set syscall(val) { - this[kInfo].syscall = val; - } - - get path() { - return this[kInfo].path !== undefined ? - this[kInfo].path.toString() : undefined; - } - - set path(val) { - this[kInfo].path = val ? - lazyBuffer().from(val.toString()) : undefined; - } - - get dest() { - return this[kInfo].path !== undefined ? - this[kInfo].dest.toString() : undefined; - } - - set dest(val) { - this[kInfo].dest = val ? - lazyBuffer().from(val.toString()) : undefined; - } -} - function createErrDiff(actual, expected, operator) { var other = ''; var res = ''; @@ -872,7 +885,9 @@ E('ERR_SOCKET_BAD_PORT', 'Port should be > 0 and < 65536. Received %s.', RangeError); E('ERR_SOCKET_BAD_TYPE', 'Bad socket type specified. Valid types are: udp4, udp6', TypeError); -E('ERR_SOCKET_BUFFER_SIZE', 'Could not get or set buffer size: %s', Error); +E('ERR_SOCKET_BUFFER_SIZE', + 'Could not get or set buffer size', + SystemError); E('ERR_SOCKET_CANNOT_SEND', 'Unable to send data', Error); E('ERR_SOCKET_CLOSED', 'Socket is closed', Error); E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running', Error); @@ -886,6 +901,7 @@ E('ERR_STREAM_UNSHIFT_AFTER_END_EVENT', 'stream.unshift() after end event', Error); E('ERR_STREAM_WRAP', 'Stream has StringDecoder set or is in objectMode', Error); E('ERR_STREAM_WRITE_AFTER_END', 'write after end', Error); +E('ERR_SYSTEM_ERROR', 'A system error occurred', SystemError); E('ERR_TLS_CERT_ALTNAME_INVALID', 'Hostname/IP does not match certificate\'s altnames: %s', Error); E('ERR_TLS_DH_PARAM_SIZE', 'DH parameter size %s is less than 2048', Error); @@ -905,6 +921,7 @@ E('ERR_TRANSFORM_ALREADY_TRANSFORMING', // This should probably be a `RangeError`. E('ERR_TRANSFORM_WITH_LENGTH_0', 'Calling transform done when writableState.length != 0', Error); +E('ERR_TTY_INIT_FAILED', 'TTY initialization failed', SystemError); E('ERR_UNCAUGHT_EXCEPTION_CAPTURE_ALREADY_SET', '`process.setupUncaughtExceptionCapture()` was called while a capture ' + 'callback was already active', @@ -945,24 +962,6 @@ E('ERR_VM_MODULE_NOT_MODULE', E('ERR_VM_MODULE_STATUS', 'Module status %s', Error); E('ERR_ZLIB_INITIALIZATION_FAILED', 'Initialization failed', Error); -function sysError(code, syscall, path, dest, - message = 'A system error occurred') { - if (code !== undefined) - message += `: ${code}`; - if (syscall !== undefined) { - if (code === undefined) - message += ':'; - message += ` [${syscall}]`; - } - if (path !== undefined) { - message += `: ${path}`; - if (dest !== undefined) - message += ` => ${dest}`; - } - return message; -} -messages.set('ERR_SYSTEM_ERROR', sysError); - function invalidArgType(name, expected, actual) { internalAssert(typeof name === 'string'); internalAssert(arguments.length === 3); diff --git a/lib/os.js b/lib/os.js index eb13139dba9..5c83dbfab7b 100644 --- a/lib/os.js +++ b/lib/os.js @@ -27,7 +27,7 @@ const { deprecate } = require('internal/util'); const { getCIDRSuffix } = require('internal/os'); const isWindows = process.platform === 'win32'; -const errors = require('internal/errors'); +const { ERR_SYSTEM_ERROR } = require('internal/errors'); const { getCPUs, @@ -49,7 +49,7 @@ function getCheckedFunction(fn) { const ctx = {}; const ret = fn(...args, ctx); if (ret === undefined) { - const err = new errors.SystemError(ctx); + const err = new ERR_SYSTEM_ERROR(ctx); Error.captureStackTrace(err, checkError); throw err; } diff --git a/lib/tty.js b/lib/tty.js index dfb76bbe53d..4e9023b0eb6 100644 --- a/lib/tty.js +++ b/lib/tty.js @@ -25,7 +25,7 @@ const { inherits, _extend } = require('util'); const net = require('net'); const { TTY, isTTY } = process.binding('tty_wrap'); const errors = require('internal/errors'); -const { ERR_INVALID_FD } = errors.codes; +const { ERR_INVALID_FD, ERR_TTY_INIT_FAILED } = errors.codes; const readline = require('readline'); const { getColorDepth } = require('internal/tty'); @@ -42,7 +42,7 @@ function ReadStream(fd, options) { const ctx = {}; const tty = new TTY(fd, true, ctx); if (ctx.code !== undefined) { - throw new errors.SystemError(ctx); + throw new ERR_TTY_INIT_FAILED(ctx); } options = _extend({ @@ -74,7 +74,7 @@ function WriteStream(fd) { const ctx = {}; const tty = new TTY(fd, false, ctx); if (ctx.code !== undefined) { - throw new errors.SystemError(ctx); + throw new ERR_TTY_INIT_FAILED(ctx); } net.Socket.call(this, { diff --git a/test/parallel/test-dgram-socket-buffer-size.js b/test/parallel/test-dgram-socket-buffer-size.js index 1fe72690d23..834ca30c57d 100644 --- a/test/parallel/test-dgram-socket-buffer-size.js +++ b/test/parallel/test-dgram-socket-buffer-size.js @@ -1,33 +1,61 @@ 'use strict'; +// Flags: --expose-internals const common = require('../common'); const assert = require('assert'); const dgram = require('dgram'); +const { SystemError } = require('internal/errors'); +const uv = process.binding('uv'); + +function getExpectedError(type) { + const code = common.isWindows ? 'ENOTSOCK' : 'EBADF'; + const message = common.isWindows ? + 'socket operation on non-socket' : 'bad file descriptor'; + const errno = common.isWindows ? uv.UV_ENOTSOCK : uv.UV_EBADF; + const syscall = `uv_${type}_buffer_size`; + const suffix = common.isWindows ? + 'ENOTSOCK (socket operation on non-socket)' : 'EBADF (bad file descriptor)'; + const error = { + code: 'ERR_SOCKET_BUFFER_SIZE', + type: SystemError, + message: `Could not get or set buffer size: ${syscall} returned ${suffix}`, + info: { + code, + message, + errno, + syscall + } + }; + return error; +} { // Should throw error if the socket is never bound. - const errorObj = { - code: 'ERR_SOCKET_BUFFER_SIZE', - type: Error, - message: /^Could not get or set buffer size:.*$/ - }; + const errorObj = getExpectedError('send'); const socket = dgram.createSocket('udp4'); common.expectsError(() => { - socket.setRecvBufferSize(8192); + socket.setSendBufferSize(8192); }, errorObj); common.expectsError(() => { - socket.setSendBufferSize(8192); + socket.getSendBufferSize(); }, errorObj); +} + +{ + const socket = dgram.createSocket('udp4'); + + // Should throw error if the socket is never bound. + const errorObj = getExpectedError('recv'); common.expectsError(() => { - socket.getRecvBufferSize(); + socket.setRecvBufferSize(8192); }, errorObj); common.expectsError(() => { - socket.getSendBufferSize(); + socket.getRecvBufferSize(); }, errorObj); } @@ -73,22 +101,48 @@ const dgram = require('dgram'); })); } -function checkBufferSizeError(type, size) { +{ + const info = { + code: 'EINVAL', + message: 'invalid argument', + errno: uv.UV_EINVAL, + syscall: 'uv_recv_buffer_size' + }; const errorObj = { code: 'ERR_SOCKET_BUFFER_SIZE', - type: Error, - message: /^Could not get or set buffer size:.*$/ + type: SystemError, + message: 'Could not get or set buffer size: uv_recv_buffer_size ' + + 'returned EINVAL (invalid argument)', + info }; - const functionName = `set${type.charAt(0).toUpperCase()}${type.slice(1)}` + - 'BufferSize'; const socket = dgram.createSocket('udp4'); socket.bind(common.mustCall(() => { common.expectsError(() => { - socket[functionName](size); + socket.setRecvBufferSize(2147483648); }, errorObj); socket.close(); })); } -checkBufferSizeError('recv', 2147483648); -checkBufferSizeError('send', 2147483648); +{ + const info = { + code: 'EINVAL', + message: 'invalid argument', + errno: uv.UV_EINVAL, + syscall: 'uv_send_buffer_size' + }; + const errorObj = { + code: 'ERR_SOCKET_BUFFER_SIZE', + type: SystemError, + message: 'Could not get or set buffer size: uv_send_buffer_size ' + + 'returned EINVAL (invalid argument)', + info + }; + const socket = dgram.createSocket('udp4'); + socket.bind(common.mustCall(() => { + common.expectsError(() => { + socket.setSendBufferSize(2147483648); + }, errorObj); + socket.close(); + })); +} diff --git a/test/parallel/test-errors-systemerror.js b/test/parallel/test-errors-systemerror.js index 45ac7341752..285c89b5d25 100644 --- a/test/parallel/test-errors-systemerror.js +++ b/test/parallel/test-errors-systemerror.js @@ -4,149 +4,79 @@ const common = require('../common'); const assert = require('assert'); const errors = require('internal/errors'); +const { AssertionError } = require('assert'); -common.expectsError( - () => { throw new errors.SystemError(); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred' - } -); - -common.expectsError( - () => { throw new errors.SystemError({}); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred' - } -); +const { E, SystemError } = errors; common.expectsError( - () => { throw new errors.SystemError(null); }, + () => { throw new errors.SystemError(); }, { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred' + code: 'ERR_ASSERTION', + type: AssertionError, + message: 'An invalid error message key was used: undefined.' } ); -common.expectsError( - () => { throw new errors.SystemError({ code: 'ERR' }); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred: ERR' - } -); +E('ERR_TEST', 'custom message', SystemError); +const { ERR_TEST } = errors.codes; { const ctx = { - code: 'ERR', - syscall: 'foo' + code: 'ETEST', + message: 'code message', + syscall: 'syscall_test', + path: '/str', + dest: '/str2' }; - common.expectsError( - () => { throw new errors.SystemError(ctx); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred: ERR [foo]' - } - ); -} -{ - const ctx = { - code: 'ERR', - syscall: 'foo', - path: Buffer.from('a') - }; common.expectsError( - () => { throw new errors.SystemError(ctx); }, + () => { throw new ERR_TEST(ctx); }, { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred: ERR [foo]: a' + code: 'ERR_TEST', + type: SystemError, + message: 'custom message: syscall_test returned ETEST (code message)' + + ' /str => /str2', + info: ctx } ); } { const ctx = { - code: 'ERR', - syscall: 'foo', - path: Buffer.from('a'), - dest: Buffer.from('b') - }; - common.expectsError( - () => { throw new errors.SystemError(ctx); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred: ERR [foo]: a => b' - } - ); -} - -{ - const ctx = { - syscall: 'foo', - path: Buffer.from('a'), - dest: Buffer.from('b') - }; - common.expectsError( - () => { throw new errors.SystemError(ctx); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred: [foo]: a => b' - } - ); -} - -{ - const ctx = { - path: Buffer.from('a'), - dest: Buffer.from('b') - }; - common.expectsError( - () => { throw new errors.SystemError(ctx); }, - { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'A system error occurred: a => b' - } - ); -} - -{ - const ctx = { - code: 'ERR', - message: 'something happened', - syscall: 'foo', - path: Buffer.from('a'), - dest: Buffer.from('b') + code: 'ETEST', + message: 'code message', + syscall: 'syscall_test', + path: Buffer.from('/buf'), + dest: '/str2' }; common.expectsError( - () => { throw new errors.SystemError(ctx); }, + () => { throw new ERR_TEST(ctx); }, { - code: 'ERR_SYSTEM_ERROR', - type: errors.SystemError, - message: 'something happened: ERR [foo]: a => b' + code: 'ERR_TEST', + type: SystemError, + message: 'custom message: syscall_test returned ETEST (code message)' + + ' /buf => /str2', + info: ctx } ); } { const ctx = { - code: 'ERR_ASSERTION' + code: 'ETEST', + message: 'code message', + syscall: 'syscall_test', + path: Buffer.from('/buf'), + dest: Buffer.from('/buf2') }; common.expectsError( - () => { throw new errors.SystemError(ctx); }, + () => { throw new ERR_TEST(ctx); }, { - code: 'ERR_ASSERTION', - type: errors.SystemError + code: 'ERR_TEST', + type: SystemError, + message: 'custom message: syscall_test returned ETEST (code message)' + + ' /buf => /buf2', + info: ctx } ); } @@ -156,20 +86,20 @@ common.expectsError( code: 'ERR', errno: 123, message: 'something happened', - syscall: 'foo', + syscall: 'syscall_test', path: Buffer.from('a'), dest: Buffer.from('b') }; - const err = new errors.SystemError(ctx); + const err = new ERR_TEST(ctx); assert.strictEqual(err.info, ctx); - assert.strictEqual(err.code, 'ERR_SYSTEM_ERROR'); + assert.strictEqual(err.code, 'ERR_TEST'); err.code = 'test'; assert.strictEqual(err.code, 'test'); // Test legacy properties. These shouldn't be used anymore // but let us make sure they still work assert.strictEqual(err.errno, 123); - assert.strictEqual(err.syscall, 'foo'); + assert.strictEqual(err.syscall, 'syscall_test'); assert.strictEqual(err.path, 'a'); assert.strictEqual(err.dest, 'b'); diff --git a/test/parallel/test-ttywrap-invalid-fd.js b/test/parallel/test-ttywrap-invalid-fd.js index adf88cbde65..c360489cb33 100644 --- a/test/parallel/test-ttywrap-invalid-fd.js +++ b/test/parallel/test-ttywrap-invalid-fd.js @@ -4,6 +4,7 @@ const common = require('../common'); const tty = require('tty'); const { SystemError } = require('internal/errors'); +const uv = process.binding('uv'); common.expectsError( () => new tty.WriteStream(-1), @@ -15,9 +16,16 @@ common.expectsError( ); { - const message = common.isWindows ? - 'bad file descriptor: EBADF [uv_tty_init]' : - 'invalid argument: EINVAL [uv_tty_init]'; + const info = { + code: common.isWindows ? 'EBADF' : 'EINVAL', + message: common.isWindows ? 'bad file descriptor' : 'invalid argument', + errno: common.isWindows ? uv.UV_EBADF : uv.UV_EINVAL, + syscall: 'uv_tty_init' + }; + + const suffix = common.isWindows ? + 'EBADF (bad file descriptor)' : 'EINVAL (invalid argument)'; + const message = `TTY initialization failed: uv_tty_init returned ${suffix}`; common.expectsError( () => { @@ -25,9 +33,10 @@ common.expectsError( new tty.WriteStream(fd); }); }, { - code: 'ERR_SYSTEM_ERROR', + code: 'ERR_TTY_INIT_FAILED', type: SystemError, - message + message, + info } ); @@ -37,9 +46,10 @@ common.expectsError( new tty.ReadStream(fd); }); }, { - code: 'ERR_SYSTEM_ERROR', + code: 'ERR_TTY_INIT_FAILED', type: SystemError, - message + message, + info }); } From 67cce8d68ad091857b583aa8564d5ac0aaaf2bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Wed, 4 Apr 2018 13:27:55 +0200 Subject: [PATCH 04/12] 2018-04-04, Version 9.11.0 (Current) Notable changes: * deps: - Updated ICU to 61.1 (Steven R. Loomis) [#19621](https://github.com/nodejs/node/pull/19621) Includes CLDR 33 (many new languages and data improvements). * fs: - Emit 'ready' event for `ReadStream` and `WriteStream` (Sameer Srivastava) [#19408](https://github.com/nodejs/node/pull/19408) * n-api: - Bump version of n-api supported (Michael Dawson) [#19497](https://github.com/nodejs/node/pull/19497) * net: - Emit 'ready' event for `Socket` (Sameer Srivastava) [#19408](https://github.com/nodejs/node/pull/19408) * Added new collaborators - [mafintosh](https://github.com/mafintosh) Mathias Buus --- CHANGELOG.md | 3 +- doc/changelogs/CHANGELOG_V9.md | 101 +++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 124ea510549..4374ebe9148 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,8 @@ release. -9.10.1
+9.11.0
+9.10.1
9.10.0
9.9.0
9.8.0
diff --git a/doc/changelogs/CHANGELOG_V9.md b/doc/changelogs/CHANGELOG_V9.md index 50cefbb97ba..e8757799e3d 100644 --- a/doc/changelogs/CHANGELOG_V9.md +++ b/doc/changelogs/CHANGELOG_V9.md @@ -9,6 +9,7 @@ +9.11.0
9.10.1
9.10.0
9.9.0
@@ -39,6 +40,106 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + +## 2018-04-04, Version 9.11.0 (Current), @MylesBorins prepared by @targos + +### Notable Changes + +* **deps**: + - Updated ICU to 61.1 (Steven R. Loomis) [#19621](https://github.com/nodejs/node/pull/19621) + Includes CLDR 33 (many new languages and data improvements). +* **fs**: + - Emit 'ready' event for `ReadStream` and `WriteStream` (Sameer Srivastava) [#19408](https://github.com/nodejs/node/pull/19408) +* **n-api**: + - Bump version of n-api supported (Michael Dawson) [#19497](https://github.com/nodejs/node/pull/19497) +* **net**: + - Emit 'ready' event for `Socket` (Sameer Srivastava) [#19408](https://github.com/nodejs/node/pull/19408) +* **Added new collaborators** + - [mafintosh](https://github.com/mafintosh) Mathias Buus + +### Commits + +* [[`0bd78dc391`](https://github.com/nodejs/node/commit/0bd78dc391)] - **buffer**: use v8::TypedArray::kMaxLength as buffer::kMaxLength (Joyee Cheung) [#19738](https://github.com/nodejs/node/pull/19738) +* [[`54b84f3c26`](https://github.com/nodejs/node/commit/54b84f3c26)] - **buffer**: remove "new" from deprecation message (Rich Trott) [#19687](https://github.com/nodejs/node/pull/19687) +* [[`0127712cf5`](https://github.com/nodejs/node/commit/0127712cf5)] - **build**: introduce make jstest (Joyee Cheung) [#19324](https://github.com/nodejs/node/pull/19324) +* [[`58f61dbf8e`](https://github.com/nodejs/node/commit/58f61dbf8e)] - **deps**: ICU 61.1 bump (Steven R. Loomis) [#19621](https://github.com/nodejs/node/pull/19621) +* [[`97a92c4973`](https://github.com/nodejs/node/commit/97a92c4973)] - **deps**: turn in std::string for ICU (Steven R. Loomis) [#19624](https://github.com/nodejs/node/pull/19624) +* [[`ae86adc086`](https://github.com/nodejs/node/commit/ae86adc086)] - **doc**: fix various nits (Vse Mozhet Byt) [#19743](https://github.com/nodejs/node/pull/19743) +* [[`041f6cd9c9`](https://github.com/nodejs/node/commit/041f6cd9c9)] - **doc**: improve Buffer.allocUnsafeSlow() and related (Rich Trott) [#19742](https://github.com/nodejs/node/pull/19742) +* [[`42671f24ba`](https://github.com/nodejs/node/commit/42671f24ba)] - **doc**: add mafintosh to collaborators (Mathias Buus) [#19773](https://github.com/nodejs/node/pull/19773) +* [[`c1b83fcbc2`](https://github.com/nodejs/node/commit/c1b83fcbc2)] - **doc**: update to adding listens on SIGUSR1 (willhayslett) [#19709](https://github.com/nodejs/node/pull/19709) +* [[`1aaad92101`](https://github.com/nodejs/node/commit/1aaad92101)] - **doc**: fix lint nits in COLLABORATOR\_GUIDE.md (Vse Mozhet Byt) [#19762](https://github.com/nodejs/node/pull/19762) +* [[`5149e18719`](https://github.com/nodejs/node/commit/5149e18719)] - **doc**: deprecation clarifications (James M Snell) [#19522](https://github.com/nodejs/node/pull/19522) +* [[`c5469bb7a8`](https://github.com/nodejs/node/commit/c5469bb7a8)] - **doc**: remove "if provided" for optional arguments (Rich Trott) [#19690](https://github.com/nodejs/node/pull/19690) +* [[`3a3ae0134d`](https://github.com/nodejs/node/commit/3a3ae0134d)] - **doc**: do not identify string as "JavaScript string" (Rich Trott) [#19689](https://github.com/nodejs/node/pull/19689) +* [[`d111037624`](https://github.com/nodejs/node/commit/d111037624)] - **doc**: favor utf16le over ucs2 in buffer.md (Rich Trott) [#19688](https://github.com/nodejs/node/pull/19688) +* [[`bb32bc8686`](https://github.com/nodejs/node/commit/bb32bc8686)] - **doc**: fix links in vm.md (Vse Mozhet Byt) [#19721](https://github.com/nodejs/node/pull/19721) +* [[`44361bd1c8`](https://github.com/nodejs/node/commit/44361bd1c8)] - **doc**: fix quotes mistypes in inline code blocks (Сковорода Никита Андреевич) [#19713](https://github.com/nodejs/node/pull/19713) +* [[`c8fa8f1f9d`](https://github.com/nodejs/node/commit/c8fa8f1f9d)] - **doc**: remove ES6/ECMAScript 2015 from buffer.md (Rich Trott) [#19685](https://github.com/nodejs/node/pull/19685) +* [[`9f20534889`](https://github.com/nodejs/node/commit/9f20534889)] - **doc**: shorten character encoding introduction (Rich Trott) [#19648](https://github.com/nodejs/node/pull/19648) +* [[`078616109c`](https://github.com/nodejs/node/commit/078616109c)] - **doc**: guard against md list parsing edge case (Vse Mozhet Byt) [#19647](https://github.com/nodejs/node/pull/19647) +* [[`2ea7f90728`](https://github.com/nodejs/node/commit/2ea7f90728)] - **doc**: fix grammar error in process.md (Kenji Okamoto) [#19641](https://github.com/nodejs/node/pull/19641) +* [[`7555deeb8c`](https://github.com/nodejs/node/commit/7555deeb8c)] - **doc**: improve zero-fill-buffers text (Rich Trott) [#19623](https://github.com/nodejs/node/pull/19623) +* [[`5e90fc6a85`](https://github.com/nodejs/node/commit/5e90fc6a85)] - **fs**: use fs.access in fs.exists (Bartosz Sosnowski) [#18618](https://github.com/nodejs/node/pull/18618) +* [[`8a8b43e1b1`](https://github.com/nodejs/node/commit/8a8b43e1b1)] - **(SEMVER-MINOR)** **fs,net**: emit 'ready' for fs streams and sockets (Sameer Srivastava) [#19408](https://github.com/nodejs/node/pull/19408) +* [[`e1f44a6366`](https://github.com/nodejs/node/commit/e1f44a6366)] - **http**: fix `request` when `setHost` is `true` (XadillaX) [#19502](https://github.com/nodejs/node/pull/19502) +* [[`dac5f67e64`](https://github.com/nodejs/node/commit/dac5f67e64)] - **http**: support server options on createServer (Wes Todd) [#19461](https://github.com/nodejs/node/pull/19461) +* [[`2bdf3ca235`](https://github.com/nodejs/node/commit/2bdf3ca235)] - **http2**: callback valid check before closing request (Trivikram) [#19061](https://github.com/nodejs/node/pull/19061) +* [[`7b850a7565`](https://github.com/nodejs/node/commit/7b850a7565)] - **http2**: destroy() stream, upon errnoException (Sarat Addepalli) [#19389](https://github.com/nodejs/node/pull/19389) +* [[`441175c29a`](https://github.com/nodejs/node/commit/441175c29a)] - **http2**: refer to stream errors by name (Anna Henningsen) [#18966](https://github.com/nodejs/node/pull/18966) +* [[`0bcad33c7a`](https://github.com/nodejs/node/commit/0bcad33c7a)] - **inspector**: report client-visible host and port (Eugene Ostroukhov) [#19664](https://github.com/nodejs/node/pull/19664) +* [[`8e440115ec`](https://github.com/nodejs/node/commit/8e440115ec)] - **lib**: add back lib/module.js redirection (Joyee Cheung) [#19177](https://github.com/nodejs/node/pull/19177) +* [[`45c477c2e6`](https://github.com/nodejs/node/commit/45c477c2e6)] - **lib**: restructure cjs and esm loaders (Joyee Cheung) [#19177](https://github.com/nodejs/node/pull/19177) +* [[`152a86c6aa`](https://github.com/nodejs/node/commit/152a86c6aa)] - **lib**: make isStackOverflowError() engine-agnostic (Mike Kaufman) [#19705](https://github.com/nodejs/node/pull/19705) +* [[`889a3b44b3`](https://github.com/nodejs/node/commit/889a3b44b3)] - **lib**: fix a typo in lib/timers "read through" (wangzengdi) [#19666](https://github.com/nodejs/node/pull/19666) +* [[`a45f3f8fd2`](https://github.com/nodejs/node/commit/a45f3f8fd2)] - **lib**: document nextTick queue internals (Anna Henningsen) [#19469](https://github.com/nodejs/node/pull/19469) +* [[`d3d1ee7279`](https://github.com/nodejs/node/commit/d3d1ee7279)] - **lib**: add internal check macros (Gus Caplan) [#18852](https://github.com/nodejs/node/pull/18852) +* [[`e0c7d783e0`](https://github.com/nodejs/node/commit/e0c7d783e0)] - **lint**: change require-buffer rule message (Gus Caplan) [#19701](https://github.com/nodejs/node/pull/19701) +* [[`859b719927`](https://github.com/nodejs/node/commit/859b719927)] - **module**: skip preserveSymlinks for main (Guy Bedford) [#19388](https://github.com/nodejs/node/pull/19388) +* [[`a0a58730e0`](https://github.com/nodejs/node/commit/a0a58730e0)] - **n-api**: back up env before finalize (Gabriel Schulhof) [#19718](https://github.com/nodejs/node/pull/19718) +* [[`b0a3a44ff6`](https://github.com/nodejs/node/commit/b0a3a44ff6)] - **n-api**: ensure in-module exceptions are propagated (Gabriel Schulhof) [#19537](https://github.com/nodejs/node/pull/19537) +* [[`94a10bad3a`](https://github.com/nodejs/node/commit/94a10bad3a)] - **(SEMVER-MINOR)** **n-api**: bump version of n-api supported (Michael Dawson) [#19497](https://github.com/nodejs/node/pull/19497) +* [[`ee4390a167`](https://github.com/nodejs/node/commit/ee4390a167)] - **repl**: fix tab completion of inspector module (Michaël Zasso) [#19505](https://github.com/nodejs/node/pull/19505) +* [[`ebdcf91dcc`](https://github.com/nodejs/node/commit/ebdcf91dcc)] - **src**: put bootstrappers in lib/internal/bootstrap/ (Joyee Cheung) [#19177](https://github.com/nodejs/node/pull/19177) +* [[`ff7a116ba3`](https://github.com/nodejs/node/commit/ff7a116ba3)] - **src**: move internal loaders out of bootstrap\_node.js (Joyee Cheung) [#19112](https://github.com/nodejs/node/pull/19112) +* [[`75d23ab2a0`](https://github.com/nodejs/node/commit/75d23ab2a0)] - **src**: fix warnings in aliased\_buffer (Kyle Farnung) [#19665](https://github.com/nodejs/node/pull/19665) +* [[`01e31906e8`](https://github.com/nodejs/node/commit/01e31906e8)] - **src**: general C++ cleanup in node\_url.cc (Anna Henningsen) [#19598](https://github.com/nodejs/node/pull/19598) +* [[`6c466811d3`](https://github.com/nodejs/node/commit/6c466811d3)] - **src**: name all builtin init functions Initialize (Daniel Bevenius) [#19550](https://github.com/nodejs/node/pull/19550) +* [[`1a38b9bd0f`](https://github.com/nodejs/node/commit/1a38b9bd0f)] - **src**: remove unused 'ares.h' include from env.h (Anna Henningsen) [#19557](https://github.com/nodejs/node/pull/19557) +* [[`cae9ff256b`](https://github.com/nodejs/node/commit/cae9ff256b)] - **src**: fix upcoming V8 deprecation warnings (Sarat Addepalli) [#19490](https://github.com/nodejs/node/pull/19490) +* [[`83ebaf08d9`](https://github.com/nodejs/node/commit/83ebaf08d9)] - **test**: remove NODE\_DEBUG in global module loading test (Joyee Cheung) [#19177](https://github.com/nodejs/node/pull/19177) +* [[`92e9ed09e9`](https://github.com/nodejs/node/commit/92e9ed09e9)] - **test**: test process.setuid for bad argument types (Divyanshu Singh) [#19703](https://github.com/nodejs/node/pull/19703) +* [[`4df3377856`](https://github.com/nodejs/node/commit/4df3377856)] - **test**: update test to comply with lint rule (Rich Trott) [#19784](https://github.com/nodejs/node/pull/19784) +* [[`f379167917`](https://github.com/nodejs/node/commit/f379167917)] - **test**: improve assert message (fatahn) [#19629](https://github.com/nodejs/node/pull/19629) +* [[`46569d644d`](https://github.com/nodejs/node/commit/46569d644d)] - **test**: remove third argument from call to assert.strictEqual() (Forrest Wolf) [#19659](https://github.com/nodejs/node/pull/19659) +* [[`e44b7779d6`](https://github.com/nodejs/node/commit/e44b7779d6)] - **test**: fix flaky test-cluster-send-handle-twice (Rich Trott) [#19700](https://github.com/nodejs/node/pull/19700) +* [[`90c85461ff`](https://github.com/nodejs/node/commit/90c85461ff)] - **test**: rename regression tests more expressively (Ujjwal Sharma) [#19668](https://github.com/nodejs/node/pull/19668) +* [[`ff7f28c4f2`](https://github.com/nodejs/node/commit/ff7f28c4f2)] - **test**: remove 3rd argument from assert.strictEqual (Arian Santrach) [#19707](https://github.com/nodejs/node/pull/19707) +* [[`0b27416516`](https://github.com/nodejs/node/commit/0b27416516)] - **test**: make test-http-expect-continue more strict (Rich Trott) [#19669](https://github.com/nodejs/node/pull/19669) +* [[`94b28aaf07`](https://github.com/nodejs/node/commit/94b28aaf07)] - **test**: use createReadStream instead of ReadStream (Daniel Bevenius) [#19636](https://github.com/nodejs/node/pull/19636) +* [[`7ae2ca4476`](https://github.com/nodejs/node/commit/7ae2ca4476)] - **test**: removed default message from assert.strictEqual (jaspal-yupana) [#19660](https://github.com/nodejs/node/pull/19660) +* [[`a89ba21ab4`](https://github.com/nodejs/node/commit/a89ba21ab4)] - **test**: refactor test-net-dns-error (Luigi Pinca) [#19640](https://github.com/nodejs/node/pull/19640) +* [[`677b613d24`](https://github.com/nodejs/node/commit/677b613d24)] - **test**: fix typo in test-tls-cnnic-whitelist (Daniel Bevenius) [#19662](https://github.com/nodejs/node/pull/19662) +* [[`806bc0d8f7`](https://github.com/nodejs/node/commit/806bc0d8f7)] - **test**: fix assert.throws error in test-http-parser (Rich Trott) [#19626](https://github.com/nodejs/node/pull/19626) +* [[`2f09ee78fb`](https://github.com/nodejs/node/commit/2f09ee78fb)] - **test**: refactor test-http-expect-continue (Rich Trott) [#19625](https://github.com/nodejs/node/pull/19625) +* [[`278e8af7a6`](https://github.com/nodejs/node/commit/278e8af7a6)] - **test**: rename tests with descriptive filenames (Ujjwal Sharma) [#19608](https://github.com/nodejs/node/pull/19608) +* [[`0daa063021`](https://github.com/nodejs/node/commit/0daa063021)] - **test**: amplify and optimize doctool/test-make-doc (Vse Mozhet Byt) [#19581](https://github.com/nodejs/node/pull/19581) +* [[`274eff5376`](https://github.com/nodejs/node/commit/274eff5376)] - **test**: update link according to NIST bibliography (Tobias Nießen) [#19593](https://github.com/nodejs/node/pull/19593) +* [[`21e69d1222`](https://github.com/nodejs/node/commit/21e69d1222)] - **test**: fix test-tty-get-color-depth (Bartosz Sosnowski) [#18478](https://github.com/nodejs/node/pull/18478) +* [[`4caf536b20`](https://github.com/nodejs/node/commit/4caf536b20)] - **test**: http2 stream.respond() error checks (Trivikram) [#18861](https://github.com/nodejs/node/pull/18861) +* [[`ca97be52a2`](https://github.com/nodejs/node/commit/ca97be52a2)] - **test**: fix wrong error classes passed in as type (Ruben Bridgewater) [#13686](https://github.com/nodejs/node/pull/13686) +* [[`44b12c158d`](https://github.com/nodejs/node/commit/44b12c158d)] - **test**: fix common.expectsError (Refael Ackermann) [#13686](https://github.com/nodejs/node/pull/13686) +* [[`cc68bc27f8`](https://github.com/nodejs/node/commit/cc68bc27f8)] - **test**: add more asserts to `test-internal-errors` (Refael Ackermann) [#13686](https://github.com/nodejs/node/pull/13686) +* [[`6bc49f03b9`](https://github.com/nodejs/node/commit/6bc49f03b9)] - **test**: http2 errors on req.close() (Trivikram) [#18854](https://github.com/nodejs/node/pull/18854) +* [[`53d7fbbbf5`](https://github.com/nodejs/node/commit/53d7fbbbf5)] - **tools**: don’t emit illegal utf-8 from icutrim/iculslocs (Steven R. Loomis) [#19756](https://github.com/nodejs/node/pull/19756) +* [[`b80d169e7c`](https://github.com/nodejs/node/commit/b80d169e7c)] - **tools**: apply editorconfig rules to tools also (Tobias Nießen) [#19521](https://github.com/nodejs/node/pull/19521) +* [[`239a036317`](https://github.com/nodejs/node/commit/239a036317)] - **tools**: remove src dir from JS editorconfig rule (Tobias Nießen) [#19521](https://github.com/nodejs/node/pull/19521) +* [[`7043e95fb7`](https://github.com/nodejs/node/commit/7043e95fb7)] - **tools**: dry utility function in tools/doc/json.js (Vse Mozhet Byt) [#19692](https://github.com/nodejs/node/pull/19692) +* [[`140611b2c6`](https://github.com/nodejs/node/commit/140611b2c6)] - **tools**: fix comment nits in tools/doc/\*.js files (Vse Mozhet Byt) [#19696](https://github.com/nodejs/node/pull/19696) +* [[`2c5d53f7cb`](https://github.com/nodejs/node/commit/2c5d53f7cb)] - **tools**: fix nits in tools/doc/type-parser.js (Vse Mozhet Byt) [#19612](https://github.com/nodejs/node/pull/19612) +* [[`fdc51a1331`](https://github.com/nodejs/node/commit/fdc51a1331)] - **url**: remove redundant function (Sergey Golovin) [#19076](https://github.com/nodejs/node/pull/19076) +* [[`99e3c77808`](https://github.com/nodejs/node/commit/99e3c77808)] - **url**: refactor "escapeParam" function to make it common (Sergey Golovin) [#19076](https://github.com/nodejs/node/pull/19076) + ## 2018-03-29, Version 9.10.1 (Current), @MylesBorins From ae2b5bcb7c17a2d2a488f234c736201eed8200db Mon Sep 17 00:00:00 2001 From: cjihrig Date: Mon, 2 Apr 2018 13:33:48 -0400 Subject: [PATCH 05/12] deps: upgrade libuv to 1.20.0 Notable changes: - uv_fs_copyfile() adds support for copy-on-write behavior. - uv_relative_path() now uses the long directory name for handle->dirw. - File operations on files > 2 GB on 32-bit platforms are working again. - uv_fs_fchmod() on Windows works on files with the Archive flag cleared. Fixes: https://github.com/nodejs/node/issues/19170 Fixes: https://github.com/nodejs/node/issues/19455 Fixes: https://github.com/nodejs/node/issues/12803 PR-URL: https://github.com/nodejs/node/pull/19758 Reviewed-By: Ben Noordhuis Reviewed-By: Santiago Gimeno Reviewed-By: James M Snell --- deps/uv/.mailmap | 1 + deps/uv/AUTHORS | 2 + deps/uv/ChangeLog | 50 ++++++++++++++ deps/uv/README.md | 6 ++ deps/uv/checksparse.sh | 2 +- deps/uv/configure.ac | 2 +- deps/uv/docs/src/fs.rst | 9 +++ deps/uv/include/uv-unix.h | 2 +- deps/uv/include/uv-version.h | 4 +- deps/uv/include/uv.h | 20 +++++- deps/uv/src/unix/core.c | 27 ++------ deps/uv/src/unix/fs.c | 44 ++++++++++++- deps/uv/src/unix/internal.h | 2 +- deps/uv/src/unix/loop.c | 3 +- deps/uv/src/unix/posix-poll.c | 14 +++- deps/uv/src/unix/process.c | 17 ++--- deps/uv/src/unix/stream.c | 6 ++ deps/uv/src/unix/tcp.c | 18 ++--- deps/uv/src/uv-common.c | 2 +- deps/uv/src/uv-common.h | 6 +- deps/uv/src/win/core.c | 6 +- deps/uv/src/win/fs-event.c | 29 +++++++- deps/uv/src/win/fs.c | 18 ++++- deps/uv/src/win/internal.h | 10 ++- deps/uv/src/win/pipe.c | 1 + deps/uv/src/win/stream-inl.h | 10 +-- deps/uv/src/win/tcp.c | 15 +++-- deps/uv/src/win/tty.c | 10 ++- deps/uv/src/win/util.c | 50 ++------------ deps/uv/test/test-connect-unspecified.c | 14 ++-- deps/uv/test/test-fs-copyfile.c | 16 +++++ deps/uv/test/test-fs-event.c | 38 ++++++++++- deps/uv/test/test-fs.c | 80 +++++++++++++++++++++++ deps/uv/test/test-list.h | 14 ++++ deps/uv/test/test-poll.c | 5 +- deps/uv/test/test-tcp-bind-error.c | 42 ++++++++++++ deps/uv/test/test-tcp-oob.c | 2 +- deps/uv/test/test-tcp-write-queue-order.c | 2 +- deps/uv/uv.gyp | 7 +- 39 files changed, 466 insertions(+), 140 deletions(-) diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index da4214365c4..5bbe5b26bb5 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.mailmap @@ -16,6 +16,7 @@ Frank Denis Imran Iqbal Isaac Z. Schlueter Jason Williams +Jesse Gorzinski Justin Venus Keno Fischer Keno Fischer diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index fcb0aac3e83..c704527a970 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -330,3 +330,5 @@ Mason X Jesse Gorzinski Ryuichi KAWAMATA Joyee Cheung +Michael Kilburn +Ruslan Bekenev diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 509a1d1571d..3ae9d2023e9 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,3 +1,53 @@ +2018.04.03, Version 1.20.0 (Stable), 0012178ee2b04d9e4a2c66c27cf8891ad8325ceb + +Changes since version 1.19.2: + +* unix,spawn: respect user stdio flags for new pipe (Jameson Nash) + +* Revert "Revert "unix,tcp: avoid marking server sockets connected"" (Jameson + Nash) + +* req: revisions to uv_req_t handling (Jameson Nash) + +* win: remove unnecessary initialization (cjihrig) + +* win: update uv_os_homedir() to use uv_os_getenv() (cjihrig) + +* test: fix tcp_oob test flakiness (Santiago Gimeno) + +* posix: fix uv__pollfds_del() for invalidated fd's (Jesse Gorzinski) + +* doc: README: add note on installing gyp (Jamie Davis) + +* unix: refactor uv_os_homedir to use uv_os_getenv (Santiago Gimeno) + +* unix: fix several instances of lost errno (Michael Kilburn) + +* win,tty: update several TODO comments (Ruslan Bekenev) + +* unix: add UV_FS_COPYFILE_FICLONE support (cjihrig) + +* test: fix connect_unspecified (Santiago Gimeno) + +* unix,win: add UV_FS_COPYFILE_FICLONE_FORCE support (cjihrig) + +* win: use long directory name for handle->dirw (Nicholas Vavilov) + +* build: build with -D_FILE_OFFSET_BITS=64 again (Ben Noordhuis) + +* win, fs: fix uv_fs_unlink for +R -A files (Bartosz Sosnowski) + +* win, fs: use FILE_WRITE_ATTRIBUTES when opening files (Bartosz Sosnowski) + +* unix: use __PASE__ on IBM i platforms (Jesse Gorzinski) + +* test,freebsd: fix flaky poll tests (Santiago Gimeno) + +* test: increase connection timeout to 1 second (jBarz) + +* win,tcp: handle canceled connect with ECANCELED (Jameson Nash) + + 2018.02.22, Version 1.19.2 (Stable), c5afc37e2a8a70d8ab0da8dac10b77ba78c0488c Changes since version 1.19.1: diff --git a/deps/uv/README.md b/deps/uv/README.md index 733171be085..1aaed1a88e7 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -169,6 +169,12 @@ $ make check $ make install ``` +To build with GYP, first run: + +```bash +$ git clone https://chromium.googlesource.com/external/gyp build/gyp +``` + ### Windows Prerequisites: diff --git a/deps/uv/checksparse.sh b/deps/uv/checksparse.sh index 27eb529bcae..d8b50bc4fec 100755 --- a/deps/uv/checksparse.sh +++ b/deps/uv/checksparse.sh @@ -184,7 +184,7 @@ AIX) src/unix/aix.c" ;; OS400) - SPARSE_FLAGS="$SPARSE_FLAGS -D_PASE=1" + SPARSE_FLAGS="$SPARSE_FLAGS -D__PASE__=1" SOURCES="$SOURCES src/unix/aix-common.c src/unix/ibmi.c diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index 4074e77841d..ee8571ea921 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.19.2], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.20.0], [https://github.com/libuv/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/as_case.m4]) diff --git a/deps/uv/docs/src/fs.rst b/deps/uv/docs/src/fs.rst index 87af828a28a..29227be0d64 100644 --- a/deps/uv/docs/src/fs.rst +++ b/deps/uv/docs/src/fs.rst @@ -249,6 +249,12 @@ API - `UV_FS_COPYFILE_EXCL`: If present, `uv_fs_copyfile()` will fail with `UV_EEXIST` if the destination path already exists. The default behavior is to overwrite the destination if it exists. + - `UV_FS_COPYFILE_FICLONE`: If present, `uv_fs_copyfile()` will attempt to + create a copy-on-write reflink. If the underlying platform does not + support copy-on-write, then a fallback copy mechanism is used. + - `UV_FS_COPYFILE_FICLONE_FORCE`: If present, `uv_fs_copyfile()` will + attempt to create a copy-on-write reflink. If the underlying platform does + not support copy-on-write, then an error is returned. .. warning:: If the destination path is created, but an error occurs while copying @@ -258,6 +264,9 @@ API .. versionadded:: 1.14.0 + .. versionchanged:: 1.20.0 `UV_FS_COPYFILE_FICLONE` and + `UV_FS_COPYFILE_FICLONE_FORCE` are supported. + .. c:function:: int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb) Limited equivalent to :man:`sendfile(2)`. diff --git a/deps/uv/include/uv-unix.h b/deps/uv/include/uv-unix.h index da32f86e847..480a0691ea3 100644 --- a/deps/uv/include/uv-unix.h +++ b/deps/uv/include/uv-unix.h @@ -48,7 +48,7 @@ # include "uv-linux.h" #elif defined (__MVS__) # include "uv-os390.h" -#elif defined(_PASE) +#elif defined(__PASE__) # include "uv-posix.h" #elif defined(_AIX) # include "uv-aix.h" diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h index c2753d51c7c..392b4d64667 100644 --- a/deps/uv/include/uv-version.h +++ b/deps/uv/include/uv-version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 19 -#define UV_VERSION_PATCH 2 +#define UV_VERSION_MINOR 20 +#define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 9794d9969b6..41fad45108b 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -378,8 +378,7 @@ UV_EXTERN const char* uv_err_name(int err); /* read-only */ \ uv_req_type type; \ /* private */ \ - void* active_queue[2]; \ - void* reserved[4]; \ + void* reserved[6]; \ UV_REQ_PRIVATE_FIELDS \ /* Abstract base class of all requests. */ @@ -1191,6 +1190,18 @@ UV_EXTERN int uv_fs_write(uv_loop_t* loop, */ #define UV_FS_COPYFILE_EXCL 0x0001 +/* + * This flag can be used with uv_fs_copyfile() to attempt to create a reflink. + * If copy-on-write is not supported, a fallback copy mechanism is used. + */ +#define UV_FS_COPYFILE_FICLONE 0x0002 + +/* + * This flag can be used with uv_fs_copyfile() to attempt to create a reflink. + * If copy-on-write is not supported, an error is returned. + */ +#define UV_FS_COPYFILE_FICLONE_FORCE 0x0004 + UV_EXTERN int uv_fs_copyfile(uv_loop_t* loop, uv_fs_t* req, const char* path, @@ -1531,7 +1542,10 @@ struct uv_loop_s { /* Loop reference counting. */ unsigned int active_handles; void* handle_queue[2]; - void* active_reqs[2]; + union { + void* unused[2]; + unsigned int count; + } active_reqs; /* Internal flag to signal loop stop. */ unsigned int stop_flag; UV_LOOP_PRIVATE_FIELDS diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 3741c1d06b2..18c8fcd808b 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -536,7 +536,7 @@ int uv__close_nocheckstdio(int fd) { int uv__close(int fd) { assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */ #if defined(__MVS__) - epoll_file_close(fd); + SAVE_ERRNO(epoll_file_close(fd)); #endif return uv__close_nocheckstdio(fd); } @@ -1048,29 +1048,16 @@ int uv__dup2_cloexec(int oldfd, int newfd) { int uv_os_homedir(char* buffer, size_t* size) { uv_passwd_t pwd; - char* buf; size_t len; int r; - if (buffer == NULL || size == NULL || *size == 0) - return UV_EINVAL; - - /* Check if the HOME environment variable is set first */ - buf = getenv("HOME"); - - if (buf != NULL) { - len = strlen(buf); + /* Check if the HOME environment variable is set first. The task of + performing input validation on buffer and size is taken care of by + uv_os_getenv(). */ + r = uv_os_getenv("HOME", buffer, size); - if (len >= *size) { - *size = len + 1; - return UV_ENOBUFS; - } - - memcpy(buffer, buf, len + 1); - *size = len; - - return 0; - } + if (r != UV_ENOENT) + return r; /* HOME is not set, so call uv__getpwuid_r() */ r = uv__getpwuid_r(&pwd); diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 92e2d255702..de678733a9c 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -62,6 +62,9 @@ #if defined(__APPLE__) # include +#elif defined(__linux__) && !defined(FICLONE) +# include +# define FICLONE _IOW(0x94, 9, int) #endif #define INIT(subtype) \ @@ -790,6 +793,19 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { if (req->flags & UV_FS_COPYFILE_EXCL) flags |= COPYFILE_EXCL; +#ifdef COPYFILE_CLONE + if (req->flags & UV_FS_COPYFILE_FICLONE) + flags |= COPYFILE_CLONE; +#endif + + if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { +#ifdef COPYFILE_CLONE_FORCE + flags |= COPYFILE_CLONE_FORCE; +#else + return UV_ENOSYS; +#endif + } + return copyfile(req->path, req->new_path, NULL, flags); #else uv_fs_t fs_req; @@ -842,6 +858,29 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { goto out; } +#ifdef FICLONE + if (req->flags & UV_FS_COPYFILE_FICLONE || + req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { + if (ioctl(dstfd, FICLONE, srcfd) == -1) { + /* If an error occurred that the sendfile fallback also won't handle, or + this is a force clone then exit. Otherwise, fall through to try using + sendfile(). */ + if ((errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) || + req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { + err = -errno; + goto out; + } + } else { + goto out; + } + } +#else + if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { + err = UV_ENOSYS; + goto out; + } +#endif + bytes_to_send = statsbuf.st_size; in_offset = 0; while (bytes_to_send != 0) { @@ -1504,8 +1543,11 @@ int uv_fs_copyfile(uv_loop_t* loop, uv_fs_cb cb) { INIT(COPYFILE); - if (flags & ~UV_FS_COPYFILE_EXCL) + if (flags & ~(UV_FS_COPYFILE_EXCL | + UV_FS_COPYFILE_FICLONE | + UV_FS_COPYFILE_FICLONE_FORCE)) { return UV_EINVAL; + } PATH2; req->flags = flags; diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 2bb3773c068..b6df1ab9d3e 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -190,7 +190,7 @@ int uv__cloexec_ioctl(int fd, int set); int uv__cloexec_fcntl(int fd, int set); int uv__nonblock_ioctl(int fd, int set); int uv__nonblock_fcntl(int fd, int set); -int uv__close(int fd); +int uv__close(int fd); /* preserves errno */ int uv__close_nocheckstdio(int fd); int uv__socket(int domain, int type, int protocol); int uv__dup(int fd); diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c index 5b5b0e095bb..99ead6cbc0c 100644 --- a/deps/uv/src/unix/loop.c +++ b/deps/uv/src/unix/loop.c @@ -38,13 +38,14 @@ int uv_loop_init(uv_loop_t* loop) { heap_init((struct heap*) &loop->timer_heap); QUEUE_INIT(&loop->wq); - QUEUE_INIT(&loop->active_reqs); QUEUE_INIT(&loop->idle_handles); QUEUE_INIT(&loop->async_handles); QUEUE_INIT(&loop->check_handles); QUEUE_INIT(&loop->prepare_handles); QUEUE_INIT(&loop->handle_queue); + loop->active_handles = 0; + loop->active_reqs.count = 0; loop->nfds = 0; loop->watchers = NULL; loop->nwatchers = 0; diff --git a/deps/uv/src/unix/posix-poll.c b/deps/uv/src/unix/posix-poll.c index f356e76c79d..f3181f9b726 100644 --- a/deps/uv/src/unix/posix-poll.c +++ b/deps/uv/src/unix/posix-poll.c @@ -107,7 +107,7 @@ static void uv__pollfds_add(uv_loop_t* loop, uv__io_t* w) { static void uv__pollfds_del(uv_loop_t* loop, int fd) { size_t i; assert(!loop->poll_fds_iterating); - for (i = 0; i < loop->poll_fds_used; ++i) { + for (i = 0; i < loop->poll_fds_used;) { if (loop->poll_fds[i].fd == fd) { /* swap to last position and remove */ --loop->poll_fds_used; @@ -115,7 +115,17 @@ static void uv__pollfds_del(uv_loop_t* loop, int fd) { loop->poll_fds[loop->poll_fds_used].fd = -1; loop->poll_fds[loop->poll_fds_used].events = 0; loop->poll_fds[loop->poll_fds_used].revents = 0; - return; + /* This method is called with an fd of -1 to purge the invalidated fds, + * so we may possibly have multiples to remove. + */ + if (-1 != fd) + return; + } else { + /* We must only increment the loop counter when the fds do not match. + * Otherwise, when we are purging an invalidated fd, the value just + * swapped here from the previous end of the array will be skipped. + */ + ++i; } } } diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index 74113e3a696..3a3cfd6f092 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -223,8 +223,7 @@ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { static int uv__process_open_stream(uv_stdio_container_t* container, - int pipefds[2], - int writable) { + int pipefds[2]) { int flags; int err; @@ -238,13 +237,11 @@ static int uv__process_open_stream(uv_stdio_container_t* container, pipefds[1] = -1; uv__nonblock(pipefds[0], 1); - if (container->data.stream->type == UV_NAMED_PIPE && - ((uv_pipe_t*)container->data.stream)->ipc) - flags = UV_STREAM_READABLE | UV_STREAM_WRITABLE; - else if (writable) - flags = UV_STREAM_WRITABLE; - else - flags = UV_STREAM_READABLE; + flags = 0; + if (container->flags & UV_WRITABLE_PIPE) + flags |= UV_STREAM_READABLE; + if (container->flags & UV_READABLE_PIPE) + flags |= UV_STREAM_WRITABLE; return uv__stream_open(container->data.stream, pipefds[0], flags); } @@ -533,7 +530,7 @@ int uv_spawn(uv_loop_t* loop, uv__close_nocheckstdio(signal_pipe[0]); for (i = 0; i < options->stdio_count; i++) { - err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0); + err = uv__process_open_stream(options->stdio + i, pipes[i]); if (err == 0) continue; diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index 3e786abee01..5ec6bf4de29 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -1417,6 +1417,9 @@ int uv_write2(uv_write_t* req, if (uv__stream_fd(stream) < 0) return UV_EBADF; + if (!(stream->flags & UV_STREAM_WRITABLE)) + return -EPIPE; + if (send_handle) { if (stream->type != UV_NAMED_PIPE || !((uv_pipe_t*)stream)->ipc) return UV_EINVAL; @@ -1568,6 +1571,9 @@ int uv_read_start(uv_stream_t* stream, if (stream->flags & UV_CLOSING) return UV_EINVAL; + if (!(stream->flags & UV_STREAM_READABLE)) + return -ENOTCONN; + /* The UV_STREAM_READING flag is irrelevant of the state of the tcp - it just * expresses the desired state of the user. */ diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c index 96f89312def..336d8e29205 100644 --- a/deps/uv/src/unix/tcp.c +++ b/deps/uv/src/unix/tcp.c @@ -49,16 +49,14 @@ static int new_socket(uv_tcp_t* handle, int domain, unsigned long flags) { /* Bind this new socket to an arbitrary port */ slen = sizeof(saddr); memset(&saddr, 0, sizeof(saddr)); - err = getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen); - if (err) { + if (getsockname(uv__stream_fd(handle), (struct sockaddr*) &saddr, &slen)) { uv__close(sockfd); - return err; + return UV__ERR(errno); } - err = bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen); - if (err) { + if (bind(uv__stream_fd(handle), (struct sockaddr*) &saddr, slen)) { uv__close(sockfd); - return err; + return UV__ERR(errno); } } @@ -158,9 +156,7 @@ int uv__tcp_bind(uv_tcp_t* tcp, if ((flags & UV_TCP_IPV6ONLY) && addr->sa_family != AF_INET6) return UV_EINVAL; - err = maybe_new_socket(tcp, - addr->sa_family, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); + err = maybe_new_socket(tcp, addr->sa_family, 0); if (err) return err; @@ -335,14 +331,14 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { if (single_accept) tcp->flags |= UV_TCP_SINGLE_ACCEPT; - flags = UV_STREAM_READABLE; + flags = 0; #if defined(__MVS__) /* on zOS the listen call does not bind automatically if the socket is unbound. Hence the manual binding to an arbitrary port is required to be done manually */ flags |= UV_HANDLE_BOUND; -#endif +#endif err = maybe_new_socket(tcp, AF_INET, flags); if (err) return err; diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index bc7d1379d13..71345895697 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -627,7 +627,7 @@ int uv_loop_close(uv_loop_t* loop) { void* saved_data; #endif - if (!QUEUE_EMPTY(&(loop)->active_reqs)) + if (uv__has_active_reqs(loop)) return UV_EBUSY; QUEUE_FOREACH(q, &loop->handle_queue) { diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index d4fa22aaef6..c497d014fd7 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -133,18 +133,18 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value); void uv__fs_scandir_cleanup(uv_fs_t* req); #define uv__has_active_reqs(loop) \ - (QUEUE_EMPTY(&(loop)->active_reqs) == 0) + ((loop)->active_reqs.count > 0) #define uv__req_register(loop, req) \ do { \ - QUEUE_INSERT_TAIL(&(loop)->active_reqs, &(req)->active_queue); \ + (loop)->active_reqs.count++; \ } \ while (0) #define uv__req_unregister(loop, req) \ do { \ assert(uv__has_active_reqs(loop)); \ - QUEUE_REMOVE(&(req)->active_queue); \ + (loop)->active_reqs.count--; \ } \ while (0) diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index 9ed4e824c6e..5fa9b6666da 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -239,7 +239,7 @@ int uv_loop_init(uv_loop_t* loop) { QUEUE_INIT(&loop->wq); QUEUE_INIT(&loop->handle_queue); - QUEUE_INIT(&loop->active_reqs); + loop->active_reqs.count = 0; loop->active_handles = 0; loop->pending_reqs_tail = NULL; @@ -470,8 +470,8 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) { static int uv__loop_alive(const uv_loop_t* loop) { - return loop->active_handles > 0 || - !QUEUE_EMPTY(&loop->active_reqs) || + return uv__has_active_handles(loop) || + uv__has_active_reqs(loop) || loop->endgame_handles != NULL; } diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c index 95f843ad08e..14c9af9ad75 100644 --- a/deps/uv/src/win/fs-event.c +++ b/deps/uv/src/win/fs-event.c @@ -69,6 +69,7 @@ static void uv_relative_path(const WCHAR* filename, size_t relpathlen; size_t filenamelen = wcslen(filename); size_t dirlen = wcslen(dir); + assert(!_wcsnicmp(filename, dir, dirlen)); if (dirlen > 0 && dir[dirlen - 1] == '\\') dirlen--; relpathlen = filenamelen - dirlen - 1; @@ -151,11 +152,11 @@ int uv_fs_event_start(uv_fs_event_t* handle, uv_fs_event_cb cb, const char* path, unsigned int flags) { - int name_size, is_path_dir; + int name_size, is_path_dir, size; DWORD attr, last_error; WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL; WCHAR short_path_buffer[MAX_PATH]; - WCHAR* short_path; + WCHAR* short_path, *long_path; if (uv__is_active(handle)) return UV_EINVAL; @@ -197,6 +198,30 @@ int uv_fs_event_start(uv_fs_event_t* handle, if (is_path_dir) { /* path is a directory, so that's the directory that we will watch. */ + + /* Convert to long path. */ + size = GetLongPathNameW(pathw, NULL, 0); + + if (size) { + long_path = (WCHAR*)uv__malloc(size * sizeof(WCHAR)); + if (!long_path) { + uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); + } + + size = GetLongPathNameW(pathw, long_path, size); + if (size) { + long_path[size] = '\0'; + } else { + uv__free(long_path); + long_path = NULL; + } + } + + if (long_path) { + uv__free(pathw); + pathw = long_path; + } + dir_to_watch = pathw; } else { /* diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 6e0bdc7bb20..b07d47cf56b 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -245,7 +245,6 @@ INLINE static void uv_fs_req_init(uv_loop_t* loop, uv_fs_t* req, req->ptr = NULL; req->path = NULL; req->cb = cb; - req->fs.info.bufs = NULL; memset(&req->fs, 0, sizeof(req->fs)); } @@ -435,6 +434,8 @@ void fs__open(uv_fs_t* req) { access |= FILE_APPEND_DATA; } + access |= FILE_WRITE_ATTRIBUTES; + /* * Here is where we deviate significantly from what CRT's _open() * does. We indiscriminately use all the sharing modes, to match @@ -784,7 +785,9 @@ void fs__unlink(uv_fs_t* req) { /* Remove read-only attribute */ FILE_BASIC_INFORMATION basic = { 0 }; - basic.FileAttributes = info.dwFileAttributes & ~(FILE_ATTRIBUTE_READONLY); + basic.FileAttributes = info.dwFileAttributes + & ~(FILE_ATTRIBUTE_READONLY) + | FILE_ATTRIBUTE_ARCHIVE; status = pNtSetInformationFile(handle, &iosb, @@ -1391,6 +1394,12 @@ static void fs__copyfile(uv_fs_t* req) { int overwrite; flags = req->fs.info.file_flags; + + if (flags & UV_FS_COPYFILE_FICLONE_FORCE) { + SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED); + return; + } + overwrite = flags & UV_FS_COPYFILE_EXCL; if (CopyFileW(req->file.pathw, req->fs.info.new_pathw, overwrite) == 0) { @@ -2335,8 +2344,11 @@ int uv_fs_copyfile(uv_loop_t* loop, INIT(UV_FS_COPYFILE); - if (flags & ~UV_FS_COPYFILE_EXCL) + if (flags & ~(UV_FS_COPYFILE_EXCL | + UV_FS_COPYFILE_FICLONE | + UV_FS_COPYFILE_FICLONE_FORCE)) { return UV_EINVAL; + } err = fs__capture_path(req, path, new_path, cb != NULL); diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index 217fcdb5d76..cce4e204d26 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -221,10 +221,16 @@ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* req); void uv_process_tty_write_req(uv_loop_t* loop, uv_tty_t* handle, uv_write_t* req); -/* TODO: remove me */ +/* + * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working + * TODO: find a way to remove it + */ void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* raw_req); -/* TODO: remove me */ +/* + * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working + * TODO: find a way to remove it + */ void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, uv_connect_t* req); diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index 1a7c4dc15e0..0ecfbf1f0e5 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -847,6 +847,7 @@ static void uv_pipe_queue_accept(uv_loop_t* loop, uv_pipe_t* handle, return; } + /* Wait for completion via IOCP */ handle->reqs_pending++; } diff --git a/deps/uv/src/win/stream-inl.h b/deps/uv/src/win/stream-inl.h index dba03747043..40f5ddd51ea 100644 --- a/deps/uv/src/win/stream-inl.h +++ b/deps/uv/src/win/stream-inl.h @@ -37,11 +37,6 @@ INLINE static void uv_stream_init(uv_loop_t* loop, handle->write_queue_size = 0; handle->activecnt = 0; handle->stream.conn.shutdown_req = NULL; -} - - -INLINE static void uv_connection_init(uv_stream_t* handle) { - handle->flags |= UV_HANDLE_CONNECTION; handle->stream.conn.write_reqs_pending = 0; UV_REQ_INIT(&handle->read_req, UV_READ); @@ -51,4 +46,9 @@ INLINE static void uv_connection_init(uv_stream_t* handle) { } +INLINE static void uv_connection_init(uv_stream_t* handle) { + handle->flags |= UV_HANDLE_CONNECTION; +} + + #endif /* UV_WIN_STREAM_INL_H_ */ diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index fd6efbaf891..39c1ff05658 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -459,8 +459,6 @@ static void uv_tcp_queue_accept(uv_tcp_t* handle, uv_tcp_accept_t* req) { INFINITE, WT_EXECUTEINWAITTHREAD)) { SET_REQ_ERROR(req, GetLastError()); uv_insert_pending_req(loop, (uv_req_t*)req); - handle->reqs_pending++; - return; } } else { /* Make this req pending reporting an error. */ @@ -1173,11 +1171,14 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, err = 0; if (REQ_SUCCESS(req)) { - if (setsockopt(handle->socket, - SOL_SOCKET, - SO_UPDATE_CONNECT_CONTEXT, - NULL, - 0) == 0) { + if (handle->flags & UV__HANDLE_CLOSING) { + /* use UV_ECANCELED for consistency with Unix */ + err = ERROR_OPERATION_ABORTED; + } else if (setsockopt(handle->socket, + SOL_SOCKET, + SO_UPDATE_CONNECT_CONTEXT, + NULL, + 0) == 0) { uv_connection_init((uv_stream_t*)handle); handle->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; loop->active_tcp_streams++; diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index 05a11e88305..ecf7bc9b5b6 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -2235,14 +2235,20 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { } -/* TODO: remove me */ +/* + * uv_process_tty_accept_req() is a stub to keep DELEGATE_STREAM_REQ working + * TODO: find a way to remove it + */ void uv_process_tty_accept_req(uv_loop_t* loop, uv_tty_t* handle, uv_req_t* raw_req) { abort(); } -/* TODO: remove me */ +/* + * uv_process_tty_connect_req() is a stub to keep DELEGATE_STREAM_REQ working + * TODO: find a way to remove it + */ void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, uv_connect_t* req) { abort(); diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c index 3100bc23ad3..3c1d9bed1db 100644 --- a/deps/uv/src/win/util.c +++ b/deps/uv/src/win/util.c @@ -1148,53 +1148,17 @@ int uv_getrusage(uv_rusage_t *uv_rusage) { int uv_os_homedir(char* buffer, size_t* size) { uv_passwd_t pwd; - wchar_t path[MAX_PATH]; - DWORD bufsize; size_t len; int r; - if (buffer == NULL || size == NULL || *size == 0) - return UV_EINVAL; - - /* Check if the USERPROFILE environment variable is set first */ - len = GetEnvironmentVariableW(L"USERPROFILE", path, MAX_PATH); - - if (len == 0) { - r = GetLastError(); - - /* Don't return an error if USERPROFILE was not found */ - if (r != ERROR_ENVVAR_NOT_FOUND) - return uv_translate_sys_error(r); - } else if (len > MAX_PATH) { - /* This should not be possible */ - return UV_EIO; - } else { - /* Check how much space we need */ - bufsize = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL); - - if (bufsize == 0) { - return uv_translate_sys_error(GetLastError()); - } else if (bufsize > *size) { - *size = bufsize; - return UV_ENOBUFS; - } - - /* Convert to UTF-8 */ - bufsize = WideCharToMultiByte(CP_UTF8, - 0, - path, - -1, - buffer, - *size, - NULL, - NULL); - - if (bufsize == 0) - return uv_translate_sys_error(GetLastError()); + /* Check if the USERPROFILE environment variable is set first. The task of + performing input validation on buffer and size is taken care of by + uv_os_getenv(). */ + r = uv_os_getenv("USERPROFILE", buffer, size); - *size = bufsize - 1; - return 0; - } + /* Don't return an error if USERPROFILE was not found. */ + if (r != UV_ENOENT) + return r; /* USERPROFILE is not set, so call uv__getpwuid_r() */ r = uv__getpwuid_r(&pwd); diff --git a/deps/uv/test/test-connect-unspecified.c b/deps/uv/test/test-connect-unspecified.c index 04e1c8a5f7c..5f32b67a6a4 100644 --- a/deps/uv/test/test-connect-unspecified.c +++ b/deps/uv/test/test-connect-unspecified.c @@ -48,12 +48,14 @@ TEST_IMPL(connect_unspecified) { (const struct sockaddr*) &addr4, connect_4) == 0); - ASSERT(uv_tcp_init(loop, &socket6) == 0); - ASSERT(uv_ip6_addr("::", TEST_PORT, &addr6) == 0); - ASSERT(uv_tcp_connect(&connect6, - &socket6, - (const struct sockaddr*) &addr6, - connect_6) == 0); + if (can_ipv6()) { + ASSERT(uv_tcp_init(loop, &socket6) == 0); + ASSERT(uv_ip6_addr("::", TEST_PORT, &addr6) == 0); + ASSERT(uv_tcp_connect(&connect6, + &socket6, + (const struct sockaddr*) &addr6, + connect_6) == 0); + } ASSERT(uv_run(loop, UV_RUN_DEFAULT) == 0); diff --git a/deps/uv/test/test-fs-copyfile.c b/deps/uv/test/test-fs-copyfile.c index 4b1fdc5e798..6cd43b45029 100644 --- a/deps/uv/test/test-fs-copyfile.c +++ b/deps/uv/test/test-fs-copyfile.c @@ -168,6 +168,22 @@ TEST_IMPL(fs_copyfile) { r = uv_fs_copyfile(loop, &req, fixture, dst, -1, fail_cb); ASSERT(r == UV_EINVAL); uv_run(loop, UV_RUN_DEFAULT); + + /* Copies file using UV_FS_COPYFILE_FICLONE. */ + unlink(dst); + r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_FICLONE, NULL); + ASSERT(r == 0); + handle_result(&req); + + /* Copies file using UV_FS_COPYFILE_FICLONE_FORCE. */ + unlink(dst); + r = uv_fs_copyfile(NULL, &req, fixture, dst, UV_FS_COPYFILE_FICLONE_FORCE, + NULL); + ASSERT(r == 0 || r == UV_ENOSYS || r == UV_ENOTSUP || r == UV_ENOTTY); + + if (r == 0) + handle_result(&req); + unlink(dst); /* Cleanup */ return 0; } diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index 39d73300dc2..5ddccffd0a9 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -129,7 +129,7 @@ static void fs_event_cb_dir(uv_fs_event_t* handle, const char* filename, ++fs_event_cb_called; ASSERT(handle == &fs_event); ASSERT(status == 0); - ASSERT(events == UV_RENAME); + ASSERT(events == UV_CHANGE); #if defined(__APPLE__) || defined(_WIN32) || defined(__linux__) ASSERT(strcmp(filename, "file1") == 0); #else @@ -477,6 +477,42 @@ TEST_IMPL(fs_event_watch_dir_recursive) { #endif } +#ifdef _WIN32 +TEST_IMPL(fs_event_watch_dir_short_path) { + uv_loop_t* loop; + int r; + + /* Setup */ + loop = uv_default_loop(); + remove("watch_dir/file1"); + remove("watch_dir/"); + create_dir("watch_dir"); + create_file("watch_dir/file1"); + + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event, fs_event_cb_dir, "watch_~1", 0); + ASSERT(r == 0); + r = uv_timer_init(loop, &timer); + ASSERT(r == 0); + r = uv_timer_start(&timer, timer_cb_file, 100, 0); + ASSERT(r == 0); + + uv_run(loop, UV_RUN_DEFAULT); + + ASSERT(fs_event_cb_called == 1); + ASSERT(timer_cb_called == 1); + ASSERT(close_cb_called == 1); + + /* Cleanup */ + remove("watch_dir/file1"); + remove("watch_dir/"); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif + TEST_IMPL(fs_event_watch_file) { #if defined(NO_FS_EVENTS) diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 3318b86649d..0075a02be66 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -1367,6 +1367,28 @@ TEST_IMPL(fs_chmod) { check_permission("test_file", 0600); +#ifdef _WIN32 + /* Test clearing read-only flag from files with Archive flag cleared */ + /* Make the file read-only and clear archive flag */ + r = SetFileAttributes("test_file", FILE_ATTRIBUTE_READONLY); + ASSERT(r != 0); + check_permission("test_file", 0400); + + r = uv_fs_open(NULL, &req, "test_file", 0, 0, NULL); + ASSERT(r >= 0); + ASSERT(req.result >= 0); + uv_fs_req_cleanup(&req); + + r = uv_fs_fchmod(NULL, &req, file, 0600, NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + uv_fs_req_cleanup(&req); + + check_permission("test_file", 0600); + /* Restore Archive flag for rest of the tests */ + r = SetFileAttributes("test_file", FILE_ATTRIBUTE_ARCHIVE); + ASSERT(r != 0); +#endif #ifndef _WIN32 /* async chmod */ { @@ -1474,6 +1496,64 @@ TEST_IMPL(fs_unlink_readonly) { return 0; } +#ifdef _WIN32 +TEST_IMPL(fs_unlink_archive_readonly) { + int r; + uv_fs_t req; + uv_file file; + + /* Setup. */ + unlink("test_file"); + + loop = uv_default_loop(); + + r = uv_fs_open(NULL, + &req, + "test_file", + O_RDWR | O_CREAT, + S_IWUSR | S_IRUSR, + NULL); + ASSERT(r >= 0); + ASSERT(req.result >= 0); + file = req.result; + uv_fs_req_cleanup(&req); + + iov = uv_buf_init(test_buf, sizeof(test_buf)); + r = uv_fs_write(NULL, &req, file, &iov, 1, -1, NULL); + ASSERT(r == sizeof(test_buf)); + ASSERT(req.result == sizeof(test_buf)); + uv_fs_req_cleanup(&req); + + close(file); + + /* Make the file read-only and clear archive flag */ + r = SetFileAttributes("test_file", FILE_ATTRIBUTE_READONLY); + ASSERT(r != 0); + uv_fs_req_cleanup(&req); + + check_permission("test_file", 0400); + + /* Try to unlink the file */ + r = uv_fs_unlink(NULL, &req, "test_file", NULL); + ASSERT(r == 0); + ASSERT(req.result == 0); + uv_fs_req_cleanup(&req); + + /* + * Run the loop just to check we don't have make any extraneous uv_ref() + * calls. This should drop out immediately. + */ + uv_run(loop, UV_RUN_DEFAULT); + + /* Cleanup. */ + uv_fs_chmod(NULL, &req, "test_file", 0600, NULL); + uv_fs_req_cleanup(&req); + unlink("test_file"); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif TEST_IMPL(fs_chown) { int r; diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index ff0a31d16bb..b89930d709e 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -95,6 +95,7 @@ TEST_DECLARE (tcp_bind_error_fault) TEST_DECLARE (tcp_bind_error_inval) TEST_DECLARE (tcp_bind_localhost_ok) TEST_DECLARE (tcp_bind_invalid_flags) +TEST_DECLARE (tcp_bind_writable_flags) TEST_DECLARE (tcp_listen_without_bind) TEST_DECLARE (tcp_connect_error_fault) TEST_DECLARE (tcp_connect_timeout) @@ -283,6 +284,9 @@ TEST_DECLARE (fs_access) TEST_DECLARE (fs_chmod) TEST_DECLARE (fs_copyfile) TEST_DECLARE (fs_unlink_readonly) +#ifdef _WIN32 +TEST_DECLARE (fs_unlink_archive_readonly) +#endif TEST_DECLARE (fs_chown) TEST_DECLARE (fs_link) TEST_DECLARE (fs_readlink) @@ -300,6 +304,9 @@ TEST_DECLARE (fs_stat_missing_path) TEST_DECLARE (fs_read_file_eof) TEST_DECLARE (fs_event_watch_dir) TEST_DECLARE (fs_event_watch_dir_recursive) +#ifdef _WIN32 +TEST_DECLARE (fs_event_watch_dir_short_path) +#endif TEST_DECLARE (fs_event_watch_file) TEST_DECLARE (fs_event_watch_file_exact_path) TEST_DECLARE (fs_event_watch_file_twice) @@ -535,6 +542,7 @@ TASK_LIST_START TEST_ENTRY (tcp_bind_error_inval) TEST_ENTRY (tcp_bind_localhost_ok) TEST_ENTRY (tcp_bind_invalid_flags) + TEST_ENTRY (tcp_bind_writable_flags) TEST_ENTRY (tcp_listen_without_bind) TEST_ENTRY (tcp_connect_error_fault) TEST_ENTRY (tcp_connect_timeout) @@ -810,6 +818,9 @@ TASK_LIST_START TEST_ENTRY (fs_chmod) TEST_ENTRY (fs_copyfile) TEST_ENTRY (fs_unlink_readonly) +#ifdef _WIN32 + TEST_ENTRY (fs_unlink_archive_readonly) +#endif TEST_ENTRY (fs_chown) TEST_ENTRY (fs_utime) TEST_ENTRY (fs_futime) @@ -826,6 +837,9 @@ TASK_LIST_START TEST_ENTRY (fs_file_open_append) TEST_ENTRY (fs_event_watch_dir) TEST_ENTRY (fs_event_watch_dir_recursive) +#ifdef _WIN32 + TEST_ENTRY (fs_event_watch_dir_short_path) +#endif TEST_ENTRY (fs_event_watch_file) TEST_ENTRY (fs_event_watch_file_exact_path) TEST_ENTRY (fs_event_watch_file_twice) diff --git a/deps/uv/test/test-poll.c b/deps/uv/test/test-poll.c index e828addbb48..0d1b1d7ec95 100644 --- a/deps/uv/test/test-poll.c +++ b/deps/uv/test/test-poll.c @@ -134,7 +134,10 @@ static void close_socket(uv_os_sock_t sock) { #else r = close(sock); #endif - ASSERT(r == 0); + /* On FreeBSD close() can fail with ECONNRESET if the socket was shutdown by + * the peer before all pending data was delivered. + */ + ASSERT(r == 0 || errno == ECONNRESET); } diff --git a/deps/uv/test/test-tcp-bind-error.c b/deps/uv/test/test-tcp-bind-error.c index 10ed68e10ec..1456d081ae6 100644 --- a/deps/uv/test/test-tcp-bind-error.c +++ b/deps/uv/test/test-tcp-bind-error.c @@ -214,3 +214,45 @@ TEST_IMPL(tcp_listen_without_bind) { MAKE_VALGRIND_HAPPY(); return 0; } + + +TEST_IMPL(tcp_bind_writable_flags) { + struct sockaddr_in addr; + uv_tcp_t server; + uv_buf_t buf; + uv_write_t write_req; + uv_shutdown_t shutdown_req; + int r; + + ASSERT(0 == uv_ip4_addr("0.0.0.0", TEST_PORT, &addr)); + r = uv_tcp_init(uv_default_loop(), &server); + ASSERT(r == 0); + r = uv_tcp_bind(&server, (const struct sockaddr*) &addr, 0); + ASSERT(r == 0); + r = uv_listen((uv_stream_t*)&server, 128, NULL); + ASSERT(r == 0); + + ASSERT(0 == uv_is_writable((uv_stream_t*) &server)); + ASSERT(0 == uv_is_readable((uv_stream_t*) &server)); + + buf = uv_buf_init("PING", 4); + r = uv_write(&write_req, (uv_stream_t*) &server, &buf, 1, NULL); + ASSERT(r == UV_EPIPE); + r = uv_shutdown(&shutdown_req, (uv_stream_t*) &server, NULL); +#ifdef _WIN32 + ASSERT(r == UV_EPIPE); +#else + ASSERT(r == UV_ENOTCONN); +#endif + r = uv_read_start((uv_stream_t*) &server, NULL, NULL); + ASSERT(r == UV_ENOTCONN); + + uv_close((uv_handle_t*)&server, close_cb); + + uv_run(uv_default_loop(), UV_RUN_DEFAULT); + + ASSERT(close_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test-tcp-oob.c b/deps/uv/test/test-tcp-oob.c index 4f1397a82ff..ca2361f9bb7 100644 --- a/deps/uv/test/test-tcp-oob.c +++ b/deps/uv/test/test-tcp-oob.c @@ -61,7 +61,7 @@ static void read_cb(uv_stream_t* handle, ssize_t nread, const uv_buf_t* buf) { #endif uv_os_fd_t fd; - ASSERT(nread > 0); + ASSERT(nread >= 0); ASSERT(0 == uv_fileno((uv_handle_t*)handle, &fd)); ASSERT(0 == uv_idle_start(&idle, idle_cb)); diff --git a/deps/uv/test/test-tcp-write-queue-order.c b/deps/uv/test/test-tcp-write-queue-order.c index 5119be6d330..1ff9c517cec 100644 --- a/deps/uv/test/test-tcp-write-queue-order.c +++ b/deps/uv/test/test-tcp-write-queue-order.c @@ -90,7 +90,7 @@ static void connection_cb(uv_stream_t* tcp, int status) { ASSERT(0 == uv_accept(tcp, (uv_stream_t*) &incoming)); ASSERT(0 == uv_timer_init(uv_default_loop(), &timer)); - ASSERT(0 == uv_timer_start(&timer, timer_cb, 1, 0)); + ASSERT(0 == uv_timer_start(&timer, timer_cb, 1000, 0)); connection_cb_called++; } diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index a5046b87ea5..e41f9ff5dce 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -2,12 +2,12 @@ 'variables': { 'conditions': [ ['OS=="win"', { + 'shared_unix_defines': [ ], + }, { 'shared_unix_defines': [ '_LARGEFILE_SOURCE', '_FILE_OFFSET_BITS=64', ], - }, { - 'shared_unix_defines': [ ], }], ['OS in "mac ios"', { 'shared_mac_defines': [ '_DARWIN_USE_64_BIT_INODE=1' ], @@ -300,9 +300,6 @@ 'src/unix/no-fsevents.c', 'src/unix/no-proctitle.c', ], - 'defines': [ - '_PASE=1' - ], }, { 'sources': [ 'src/unix/aix.c' From 0876a0314d15129e8b29cb6e9753b886086cbfe2 Mon Sep 17 00:00:00 2001 From: John-David Dalton Date: Sun, 25 Mar 2018 11:02:49 -0700 Subject: [PATCH 06/12] lib: ensure --check flag works with --require PR-URL: https://github.com/nodejs/node/pull/19600 Reviewed-By: James M Snell Reviewed-By: Anna Henningsen Reviewed-By: Richard Lau --- doc/api/cli.md | 4 ++++ lib/internal/bootstrap/node.js | 12 ++++++------ test/fixtures/no-wrapper.js | 1 + test/parallel/test-cli-syntax.js | 23 +++++++++++++++++++++++ 4 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 test/fixtures/no-wrapper.js diff --git a/doc/api/cli.md b/doc/api/cli.md index 1a200b26fee..33882e32854 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -75,6 +75,10 @@ Identical to `-e` but prints the result. added: - v5.0.0 - v4.2.0 +changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/19600 + description: The `--require` option is now supported when checking a file. --> Syntax check the script without executing. diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index 99bf00a6d6e..7762aac8469 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -210,6 +210,12 @@ const CJSModule = NativeModule.require('internal/modules/cjs/loader'); + perf.markMilestone(NODE_PERFORMANCE_MILESTONE_MODULE_LOAD_END); + perf.markMilestone( + NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_START); + preloadModules(); + perf.markMilestone( + NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_END); // check if user passed `-c` or `--check` arguments to Node. if (process._syntax_check_only != null) { const fs = NativeModule.require('fs'); @@ -219,12 +225,6 @@ checkScriptSyntax(source, filename); process.exit(0); } - perf.markMilestone(NODE_PERFORMANCE_MILESTONE_MODULE_LOAD_END); - perf.markMilestone( - NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_START); - preloadModules(); - perf.markMilestone( - NODE_PERFORMANCE_MILESTONE_PRELOAD_MODULE_LOAD_END); CJSModule.runMain(); } else { perf.markMilestone(NODE_PERFORMANCE_MILESTONE_MODULE_LOAD_START); diff --git a/test/fixtures/no-wrapper.js b/test/fixtures/no-wrapper.js new file mode 100644 index 00000000000..d8c6aca111d --- /dev/null +++ b/test/fixtures/no-wrapper.js @@ -0,0 +1 @@ +require('module').wrapper = ['', '']; diff --git a/test/parallel/test-cli-syntax.js b/test/parallel/test-cli-syntax.js index 0b1010c4dad..d80e8c698d7 100644 --- a/test/parallel/test-cli-syntax.js +++ b/test/parallel/test-cli-syntax.js @@ -140,3 +140,26 @@ syntaxArgs.forEach(function(args) { })); }); }); + +// should work with -r flags +['-c', '--check'].forEach(function(checkFlag) { + ['-r', '--require'].forEach(function(requireFlag) { + const preloadFile = fixtures.path('no-wrapper.js'); + const file = fixtures.path('syntax', 'illegal_if_not_wrapped.js'); + const args = [requireFlag, preloadFile, checkFlag, file]; + const cmd = [node, ...args].join(' '); + exec(cmd, common.mustCall((err, stdout, stderr) => { + assert.strictEqual(err instanceof Error, true); + assert.strictEqual(err.code, 1); + + // no stdout should be produced + assert.strictEqual(stdout, ''); + + // stderr should have a syntax error message + assert(syntaxErrorRE.test(stderr), `${syntaxErrorRE} === ${stderr}`); + + // stderr should include the filename + assert(stderr.startsWith(file), `${stderr} starts with ${file}`); + })); + }); +}); From 126b03e2f9e5a695b025a1a70eb49b88de43d080 Mon Sep 17 00:00:00 2001 From: willhayslett Date: Sun, 25 Mar 2018 21:56:06 -0500 Subject: [PATCH 07/12] test: add tests for fs/promises.js fileHandle methods Working to increase test code coverage for fs/promises.js. Added tests for fileHandle.appendFile and fileHandle.chmod. PR-URL: https://github.com/nodejs/node/pull/19605 Reviewed-By: James M Snell Reviewed-By: Rich Trott --- ...est-fs-promises-file-handle-append-file.js | 41 +++++++++++++++++ .../test-fs-promises-file-handle-chmod.js | 44 ++++++++++++++++++ .../test-fs-promises-file-handle-read.js | 45 +++++++++++++++++++ .../test-fs-promises-file-handle-readFile.js | 32 +++++++++++++ .../test-fs-promises-file-handle-write.js | 40 +++++++++++++++++ .../test-fs-promises-file-handle-writeFile.js | 29 ++++++++++++ 6 files changed, 231 insertions(+) create mode 100644 test/parallel/test-fs-promises-file-handle-append-file.js create mode 100644 test/parallel/test-fs-promises-file-handle-chmod.js create mode 100644 test/parallel/test-fs-promises-file-handle-read.js create mode 100644 test/parallel/test-fs-promises-file-handle-readFile.js create mode 100644 test/parallel/test-fs-promises-file-handle-write.js create mode 100644 test/parallel/test-fs-promises-file-handle-writeFile.js diff --git a/test/parallel/test-fs-promises-file-handle-append-file.js b/test/parallel/test-fs-promises-file-handle-append-file.js new file mode 100644 index 00000000000..38336a2b43a --- /dev/null +++ b/test/parallel/test-fs-promises-file-handle-append-file.js @@ -0,0 +1,41 @@ +'use strict'; + +const common = require('../common'); + +// The following tests validate base functionality for the fs/promises +// FileHandle.appendFile method. + +const fs = require('fs'); +const { open } = require('fs/promises'); +const path = require('path'); +const tmpdir = require('../common/tmpdir'); +const assert = require('assert'); +const tmpDir = tmpdir.path; + +tmpdir.refresh(); +common.crashOnUnhandledRejection(); + +async function validateAppendBuffer() { + const filePath = path.resolve(tmpDir, 'tmp-append-file-buffer.txt'); + const fileHandle = await open(filePath, 'a'); + const buffer = Buffer.from('a&Dp'.repeat(100), 'utf8'); + + await fileHandle.appendFile(buffer); + const appendedFileData = fs.readFileSync(filePath); + assert.deepStrictEqual(appendedFileData, buffer); +} + +async function validateAppendString() { + const filePath = path.resolve(tmpDir, 'tmp-append-file-string.txt'); + const fileHandle = await open(filePath, 'a'); + const string = 'x~yz'.repeat(100); + + await fileHandle.appendFile(string); + const stringAsBuffer = Buffer.from(string, 'utf8'); + const appendedFileData = fs.readFileSync(filePath); + assert.deepStrictEqual(appendedFileData, stringAsBuffer); +} + +validateAppendBuffer() + .then(validateAppendString) + .then(common.mustCall()); diff --git a/test/parallel/test-fs-promises-file-handle-chmod.js b/test/parallel/test-fs-promises-file-handle-chmod.js new file mode 100644 index 00000000000..c2a44fba7bd --- /dev/null +++ b/test/parallel/test-fs-promises-file-handle-chmod.js @@ -0,0 +1,44 @@ +'use strict'; + +const common = require('../common'); + +// The following tests validate base functionality for the fs/promises +// FileHandle.chmod method. + +const fs = require('fs'); +const { open } = require('fs/promises'); +const path = require('path'); +const tmpdir = require('../common/tmpdir'); +const assert = require('assert'); +const tmpDir = tmpdir.path; + +tmpdir.refresh(); +common.crashOnUnhandledRejection(); + +async function validateFilePermission() { + const filePath = path.resolve(tmpDir, 'tmp-chmod.txt'); + const fileHandle = await open(filePath, 'w+', 0o444); + // file created with r--r--r-- 444 + const statsBeforeMod = fs.statSync(filePath); + assert.deepStrictEqual(statsBeforeMod.mode & 0o444, 0o444); + + let expectedAccess; + const newPermissions = 0o765; + + if (common.isWindows) { + // chmod in Windows will only toggle read only/write access. the + // fs.Stats.mode in Windows is computed using read/write + // bits (not exec). read only at best returns 444; r/w 666. + // refer: /deps/uv/src/win/fs.cfs; + expectedAccess = 0o664; + } else { + expectedAccess = newPermissions; + } + + // change the permissions to rwxr--r-x + await fileHandle.chmod(newPermissions); + const statsAfterMod = fs.statSync(filePath); + assert.deepStrictEqual(statsAfterMod.mode & expectedAccess, expectedAccess); +} + +validateFilePermission().then(common.mustCall()); diff --git a/test/parallel/test-fs-promises-file-handle-read.js b/test/parallel/test-fs-promises-file-handle-read.js new file mode 100644 index 00000000000..5a9bc4558cf --- /dev/null +++ b/test/parallel/test-fs-promises-file-handle-read.js @@ -0,0 +1,45 @@ +'use strict'; + +const common = require('../common'); + +// The following tests validate base functionality for the fs/promises +// FileHandle.read method. + +const fs = require('fs'); +const { open } = require('fs/promises'); +const path = require('path'); +const tmpdir = require('../common/tmpdir'); +const assert = require('assert'); +const tmpDir = tmpdir.path; + +tmpdir.refresh(); +common.crashOnUnhandledRejection(); + +async function validateRead() { + const filePath = path.resolve(tmpDir, 'tmp-read-file.txt'); + const fileHandle = await open(filePath, 'w+'); + const buffer = Buffer.from('Hello world', 'utf8'); + + const fd = fs.openSync(filePath, 'w+'); + fs.writeSync(fd, buffer, 0, buffer.length); + fs.closeSync(fd); + const readAsyncHandle = await fileHandle.read(Buffer.alloc(11), 0, 11, 0); + assert.deepStrictEqual(buffer.length, readAsyncHandle.bytesRead); + assert.deepStrictEqual(buffer, readAsyncHandle.buffer); +} + +async function validateEmptyRead() { + const filePath = path.resolve(tmpDir, 'tmp-read-empty-file.txt'); + const fileHandle = await open(filePath, 'w+'); + const buffer = Buffer.from('', 'utf8'); + + const fd = fs.openSync(filePath, 'w+'); + fs.writeSync(fd, buffer, 0, buffer.length); + fs.closeSync(fd); + const readAsyncHandle = await fileHandle.read(Buffer.alloc(11), 0, 11, 0); + assert.deepStrictEqual(buffer.length, readAsyncHandle.bytesRead); +} + +validateRead() + .then(validateEmptyRead) + .then(common.mustCall()); diff --git a/test/parallel/test-fs-promises-file-handle-readFile.js b/test/parallel/test-fs-promises-file-handle-readFile.js new file mode 100644 index 00000000000..9308c299092 --- /dev/null +++ b/test/parallel/test-fs-promises-file-handle-readFile.js @@ -0,0 +1,32 @@ +'use strict'; + +const common = require('../common'); + +// The following tests validate base functionality for the fs/promises +// FileHandle.readFile method. + +const fs = require('fs'); +const { open } = require('fs/promises'); +const path = require('path'); +const tmpdir = require('../common/tmpdir'); +const assert = require('assert'); +const tmpDir = tmpdir.path; + +tmpdir.refresh(); +common.crashOnUnhandledRejection(); + +async function validateReadFile() { + const filePath = path.resolve(tmpDir, 'tmp-read-file.txt'); + const fileHandle = await open(filePath, 'w+'); + const buffer = Buffer.from('Hello world'.repeat(100), 'utf8'); + + const fd = fs.openSync(filePath, 'w+'); + fs.writeSync(fd, buffer, 0, buffer.length); + fs.closeSync(fd); + + const readFileData = await fileHandle.readFile(); + assert.deepStrictEqual(buffer, readFileData); +} + +validateReadFile() + .then(common.mustCall()); diff --git a/test/parallel/test-fs-promises-file-handle-write.js b/test/parallel/test-fs-promises-file-handle-write.js new file mode 100644 index 00000000000..842095a214c --- /dev/null +++ b/test/parallel/test-fs-promises-file-handle-write.js @@ -0,0 +1,40 @@ +'use strict'; + +const common = require('../common'); + +// The following tests validate base functionality for the fs/promises +// FileHandle.read method. + +const fs = require('fs'); +const { open } = require('fs/promises'); +const path = require('path'); +const tmpdir = require('../common/tmpdir'); +const assert = require('assert'); +const tmpDir = tmpdir.path; + +tmpdir.refresh(); +common.crashOnUnhandledRejection(); + +async function validateWrite() { + const filePathForHandle = path.resolve(tmpDir, 'tmp-write.txt'); + const fileHandle = await open(filePathForHandle, 'w+'); + const buffer = Buffer.from('Hello world'.repeat(100), 'utf8'); + + await fileHandle.write(buffer, 0, buffer.length); + const readFileData = fs.readFileSync(filePathForHandle); + assert.deepStrictEqual(buffer, readFileData); +} + +async function validateEmptyWrite() { + const filePathForHandle = path.resolve(tmpDir, 'tmp-empty-write.txt'); + const fileHandle = await open(filePathForHandle, 'w+'); + const buffer = Buffer.from(''); // empty buffer + + await fileHandle.write(buffer, 0, buffer.length); + const readFileData = fs.readFileSync(filePathForHandle); + assert.deepStrictEqual(buffer, readFileData); +} + +validateWrite() + .then(validateEmptyWrite) + .then(common.mustCall()); diff --git a/test/parallel/test-fs-promises-file-handle-writeFile.js b/test/parallel/test-fs-promises-file-handle-writeFile.js new file mode 100644 index 00000000000..196b6f8db8c --- /dev/null +++ b/test/parallel/test-fs-promises-file-handle-writeFile.js @@ -0,0 +1,29 @@ +'use strict'; + +const common = require('../common'); + +// The following tests validate base functionality for the fs/promises +// FileHandle.readFile method. + +const fs = require('fs'); +const { open } = require('fs/promises'); +const path = require('path'); +const tmpdir = require('../common/tmpdir'); +const assert = require('assert'); +const tmpDir = tmpdir.path; + +tmpdir.refresh(); +common.crashOnUnhandledRejection(); + +async function validateWriteFile() { + const filePathForHandle = path.resolve(tmpDir, 'tmp-write-file2.txt'); + const fileHandle = await open(filePathForHandle, 'w+'); + const buffer = Buffer.from('Hello world'.repeat(100), 'utf8'); + + await fileHandle.writeFile(buffer); + const readFileData = fs.readFileSync(filePathForHandle); + assert.deepStrictEqual(buffer, readFileData); +} + +validateWriteFile() + .then(common.mustCall()); From 49e9893d859f0dccd42bea731669cce3f0c2f9f9 Mon Sep 17 00:00:00 2001 From: Myles Borins Date: Wed, 4 Apr 2018 23:07:27 -0400 Subject: [PATCH 08/12] 2018-04-05, Version 9.11.1 (Current) Notable changes: An infrastructure issue caused a non-functioning msi installer for x64 to be promoted. The patch release is to ensure that all binaries and installers work as expected. --- CHANGELOG.md | 3 ++- doc/changelogs/CHANGELOG_V9.md | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4374ebe9148..96fde728261 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,8 @@ release. -9.11.0
+9.11.1
+9.11.0
9.10.1
9.10.0
9.9.0
diff --git a/doc/changelogs/CHANGELOG_V9.md b/doc/changelogs/CHANGELOG_V9.md index e8757799e3d..2180c59f4ff 100644 --- a/doc/changelogs/CHANGELOG_V9.md +++ b/doc/changelogs/CHANGELOG_V9.md @@ -9,6 +9,7 @@ +9.11.1
9.11.0
9.10.1
9.10.0
@@ -40,6 +41,16 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) + +## 2018-04-05, Version 9.11.1 (Current), @MylesBorins + +### Notable Changes + +No additional commits. + +An infrastructure issue caused a non-functioning msi installer for x64 to be promoted. +The patch release is to ensure that all binaries and installers work as expected. + ## 2018-04-04, Version 9.11.0 (Current), @MylesBorins prepared by @targos From 422ac61535fd190836b174bb6ad8ec2af76e1f05 Mon Sep 17 00:00:00 2001 From: Trivikram Kamat <16024985+trivikr@users.noreply.github.com> Date: Wed, 4 Apr 2018 07:51:26 -0700 Subject: [PATCH 09/12] doc: remove link to "breaking changes" wiki Breaking changes wiki is not updated, so removing the paragraph PR-URL: https://github.com/nodejs/node/pull/19795 Reviewed-By: Vse Mozhet Byt Reviewed-By: Luigi Pinca Reviewed-By: Rich Trott Reviewed-By: James M Snell --- doc/guides/contributing/pull-requests.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/guides/contributing/pull-requests.md b/doc/guides/contributing/pull-requests.md index 9220ab4e8e6..7aaf30c62b2 100644 --- a/doc/guides/contributing/pull-requests.md +++ b/doc/guides/contributing/pull-requests.md @@ -165,10 +165,6 @@ use `Refs:`. contain an explanation about the reason of the breaking change, which situation would trigger the breaking change and what is the exact change. -Breaking changes will be listed in the wiki with the aim to make upgrading -easier. Please have a look at [Breaking Changes](https://github.com/nodejs/node/wiki/Breaking-changes-between-v4-LTS-and-v6-LTS) -for the level of detail that's suitable. - Sample complete commit message: ```txt From 354849eeb595ac364337e564669de4c77aa4c1af Mon Sep 17 00:00:00 2001 From: Sergey Golovin Date: Mon, 12 Mar 2018 18:59:31 +0300 Subject: [PATCH 10/12] url: replace "magic" numbers by constants PR-URL: https://github.com/nodejs/node/pull/19300 Reviewed-By: James M Snell Reviewed-By: Daijiro Wachi Reviewed-By: Gibson Fahnestock --- lib/internal/constants.js | 2 ++ lib/internal/url.js | 18 +++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/lib/internal/constants.js b/lib/internal/constants.js index 6fc16e57d95..5c884ae6bc4 100644 --- a/lib/internal/constants.js +++ b/lib/internal/constants.js @@ -39,6 +39,8 @@ module.exports = { CHAR_CIRCUMFLEX_ACCENT: 94, /* ^ */ CHAR_GRAVE_ACCENT: 96, /* ` */ CHAR_AT: 64, /* @ */ + CHAR_AMPERSAND: 38, /* & */ + CHAR_EQUAL: 61, /* = */ // Digits CHAR_0: 48, /* 0 */ diff --git a/lib/internal/url.js b/lib/internal/url.js index 1513b14e829..21c7c734b58 100644 --- a/lib/internal/url.js +++ b/lib/internal/url.js @@ -19,6 +19,14 @@ const { ERR_INVALID_URL_SCHEME, ERR_MISSING_ARGS } = require('internal/errors').codes; +const { + CHAR_PERCENT, + CHAR_PLUS, + CHAR_AMPERSAND, + CHAR_EQUAL, + CHAR_LOWERCASE_A, + CHAR_LOWERCASE_Z, +} = require('internal/constants'); const querystring = require('querystring'); const { platform } = process; @@ -712,7 +720,7 @@ function parseParams(qs) { const code = qs.charCodeAt(i); // Try matching key/value pair separator - if (code === 38/* & */) { + if (code === CHAR_AMPERSAND) { if (pairStart === i) { // We saw an empty substring between pair separators lastPos = pairStart = i + 1; @@ -738,7 +746,7 @@ function parseParams(qs) { } // Try matching key/value separator (e.g. '=') if we haven't already - if (!seenSep && code === 61/* = */) { + if (!seenSep && code === CHAR_EQUAL) { // Key/value separator match! if (lastPos < i) buf += qs.slice(lastPos, i); @@ -755,7 +763,7 @@ function parseParams(qs) { } // Handle + and percent decoding. - if (code === 43/* + */) { + if (code === CHAR_PLUS) { if (lastPos < i) buf += qs.slice(lastPos, i); buf += ' '; @@ -763,7 +771,7 @@ function parseParams(qs) { } else if (!encoded) { // Try to match an (valid) encoded byte (once) to minimize unnecessary // calls to string decoding functions - if (code === 37/* % */) { + if (code === CHAR_PERCENT) { encodeCheck = 1; } else if (encodeCheck > 0) { // eslint-disable-next-line no-extra-boolean-cast @@ -1357,7 +1365,7 @@ function getPathFromURLWin32(url) { // Otherwise, it's a local path that requires a drive letter var letter = pathname.codePointAt(1) | 0x20; var sep = pathname[2]; - if (letter < 97 || letter > 122 || // a..z A..Z + if (letter < CHAR_LOWERCASE_A || letter > CHAR_LOWERCASE_Z || // a..z A..Z (sep !== ':')) { throw new ERR_INVALID_FILE_URL_PATH('must be absolute'); } From 22da2f731d90235289a95bffe1ae3750a62a33bc Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sun, 1 Apr 2018 07:38:47 +0200 Subject: [PATCH 11/12] errors: make message non-enumerable A error message should always be non-enumerable. This makes sure that is true for dns errors as well. It also adds another check in `common.expectsError` to make sure no other regressions are introduced going forward. Fixes #19716 PR-URL: https://github.com/nodejs/node/pull/19719 Fixes: https://github.com/nodejs/node/issues/19716 Reviewed-By: Joyee Cheung Reviewed-By: Luigi Pinca Reviewed-By: Trivikram Kamat Reviewed-By: James M Snell --- lib/internal/errors.js | 37 +++++++++---------- test/common/index.js | 3 ++ test/parallel/test-dns-lookup.js | 3 ++ .../test-dns-resolveany-bad-ancount.js | 3 ++ 4 files changed, 27 insertions(+), 19 deletions(-) diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 17b6f966d42..3e940c84968 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -550,34 +550,33 @@ function exceptionWithHostPort(err, syscall, address, port, additional) { } /** - * @param {number|string} err - A libuv error number or a c-ares error code + * @param {number|string} code - A libuv error number or a c-ares error code * @param {string} syscall * @param {string} [hostname] * @returns {Error} */ -function dnsException(err, syscall, hostname) { - // eslint-disable-next-line no-restricted-syntax - const ex = new Error(); +function dnsException(code, syscall, hostname) { + let message; // 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 (code === UV_EAI_MEMORY || + code === UV_EAI_NODATA || + code === UV_EAI_NONAME) { + code = '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; + if (typeof code === 'string') { // c-ares error code. + message = `${syscall} ${code}${hostname ? ` ${hostname}` : ''}`; } 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; + code = lazyInternalUtil().getSystemErrorName(code); + message = `${syscall} ${code}`; } + // eslint-disable-next-line no-restricted-syntax + const ex = new Error(message); + // TODO(joyeecheung): errno is supposed to be a number / err, like in + // uvException. + ex.errno = code; + ex.code = code; + ex.syscall = syscall; if (hostname) { ex.hostname = hostname; } diff --git a/test/common/index.js b/test/common/index.js index ba53065ef01..1a444f0dbd1 100644 --- a/test/common/index.js +++ b/test/common/index.js @@ -691,6 +691,9 @@ exports.expectsError = function expectsError(fn, settings, exact) { fn = undefined; } function innerFn(error) { + const descriptor = Object.getOwnPropertyDescriptor(error, 'message'); + assert.strictEqual(descriptor.enumerable, + false, 'The error message should be non-enumerable'); if ('type' in settings) { const type = settings.type; if (type !== Error && !Error.isPrototypeOf(type)) { diff --git a/test/parallel/test-dns-lookup.js b/test/parallel/test-dns-lookup.js index d006355742e..b9c0dfc6dff 100644 --- a/test/parallel/test-dns-lookup.js +++ b/test/parallel/test-dns-lookup.js @@ -92,6 +92,9 @@ dns.lookup('example.com', common.mustCall((error, result, addressType) => { assert(error); assert.strictEqual(tickValue, 1); assert.strictEqual(error.code, 'ENOENT'); + const descriptor = Object.getOwnPropertyDescriptor(error, 'message'); + assert.strictEqual(descriptor.enumerable, + false, 'The error message should be non-enumerable'); })); // Make sure that the error callback is called diff --git a/test/parallel/test-dns-resolveany-bad-ancount.js b/test/parallel/test-dns-resolveany-bad-ancount.js index 25ce15935ca..63ed1774b11 100644 --- a/test/parallel/test-dns-resolveany-bad-ancount.js +++ b/test/parallel/test-dns-resolveany-bad-ancount.js @@ -30,6 +30,9 @@ server.bind(0, common.mustCall(() => { assert.strictEqual(err.code, 'EBADRESP'); assert.strictEqual(err.syscall, 'queryAny'); assert.strictEqual(err.hostname, 'example.org'); + const descriptor = Object.getOwnPropertyDescriptor(err, 'message'); + assert.strictEqual(descriptor.enumerable, + false, 'The error message should be non-enumerable'); server.close(); })); })); From b29c36b80746733994257b7380245102bc3c4cd6 Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sun, 1 Apr 2018 07:54:32 +0200 Subject: [PATCH 12/12] errors: make dns errors consistent Right now the hostname could in some cases be missed, depending on the libuv error number. This makes sure there the hostname is always added, if available. PR-URL: https://github.com/nodejs/node/pull/19754 Reviewed-By: Joyee Cheung Reviewed-By: Matteo Collina Reviewed-By: James M Snell --- lib/dns.js | 2 +- lib/internal/errors.js | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/lib/dns.js b/lib/dns.js index cb8b2ca0beb..fdfcec2e7ee 100644 --- a/lib/dns.js +++ b/lib/dns.js @@ -229,7 +229,7 @@ function resolver(bindingName) { req.oncomplete = onresolve; req.ttl = !!(options && options.ttl); var err = this._handle[bindingName](req, name); - if (err) throw dnsException(err, bindingName); + if (err) throw dnsException(err, bindingName, name); return req; } Object.defineProperty(query, 'name', { value: bindingName }); diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 3e940c84968..2fe081bda74 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -556,20 +556,20 @@ function exceptionWithHostPort(err, syscall, address, port, additional) { * @returns {Error} */ function dnsException(code, syscall, hostname) { - let message; - // FIXME(bnoordhuis) Remove this backwards compatibility nonsense and pass - // the true error to the user. ENOTFOUND is not even a proper POSIX error! - if (code === UV_EAI_MEMORY || - code === UV_EAI_NODATA || - code === UV_EAI_NONAME) { - code = 'ENOTFOUND'; // Fabricated error name. - } - if (typeof code === 'string') { // c-ares error code. - message = `${syscall} ${code}${hostname ? ` ${hostname}` : ''}`; - } else { // libuv error number - code = lazyInternalUtil().getSystemErrorName(code); - message = `${syscall} ${code}`; + // If `code` is of type number, it is a libuv error number, else it is a + // c-ares error code. + if (typeof code === 'number') { + // FIXME(bnoordhuis) Remove this backwards compatibility nonsense and pass + // the true error to the user. ENOTFOUND is not even a proper POSIX error! + if (code === UV_EAI_MEMORY || + code === UV_EAI_NODATA || + code === UV_EAI_NONAME) { + code = 'ENOTFOUND'; // Fabricated error name. + } else { + code = lazyInternalUtil().getSystemErrorName(code); + } } + const message = `${syscall} ${code}${hostname ? ` ${hostname}` : ''}`; // eslint-disable-next-line no-restricted-syntax const ex = new Error(message); // TODO(joyeecheung): errno is supposed to be a number / err, like in