diff --git a/BUILDING.md b/BUILDING.md index 95d62c481cce80..96c42304db2a8d 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -215,7 +215,8 @@ Prerequisites: [Git for Windows](http://git-scm.com/download/win) includes Git Bash and tools which can be included in the global `PATH`. -If the path to your build directory contains a space, the build will likely fail. +If the path to your build directory contains a space or a non-ASCII character, the +build will likely fail. ```console > .\vcbuild nosign @@ -385,3 +386,26 @@ and [user guide](https://openssl.org/docs/fips/UserGuide-2.0.pdf). `/usr/local/ssl/fips-2.0` 8. Build Node.js with `make -j` 9. Verify with `node -p "process.versions.openssl"` (for example `1.0.2a-fips`) + +## Building Node.js with external core modules + +It is possible to specify one or more JavaScript text files to be bundled in +the binary as builtin modules when building Node.js. + +### Unix / macOS + +This command will make `/root/myModule.js` available via +`require('/root/myModule')` and `./myModule2.js` available via +`require('myModule2')`. + +```console +$ ./configure --link-module '/root/myModule.js' --link-module './myModule2.js' +``` + +### Windows + +To make `./myCustomModule.js` available via `require('myCustomModule')`. + +```console +> .\vcbuild link-module './myCustomModule.js' +``` diff --git a/COLLABORATOR_GUIDE.md b/COLLABORATOR_GUIDE.md index 78401264844c52..7d8d70cdac38e0 100644 --- a/COLLABORATOR_GUIDE.md +++ b/COLLABORATOR_GUIDE.md @@ -127,12 +127,14 @@ Before landing pull requests, sufficient time should be left for input from other Collaborators. In general, leave at least 48 hours during the week and 72 hours over weekends to account for international time differences and work schedules. However, certain types of pull requests -can be fast-tracked and may be landed after a shorter delay: - -* Focused changes that affect only documentation and/or the test suite. - `code-and-learn` and `good-first-issue` pull requests typically fall - into this category. -* Changes that fix regressions. +can be fast-tracked and may be landed after a shorter delay. For example: + +* Focused changes that affect only documentation and/or the test suite: + * `code-and-learn` tasks typically fall into this category. + * `good-first-issue` pull requests may also be suitable. +* Changes that fix regressions: + * Regressions that break the workflow (red CI or broken compilation). + * Regressions that happen right before a release, or reported soon after. When a pull request is deemed suitable to be fast-tracked, label it with `fast-track`. The pull request can be landed once 2 or more Collaborators diff --git a/README.md b/README.md index 43d2bad78234b3..55ad1756f15c1e 100644 --- a/README.md +++ b/README.md @@ -408,8 +408,8 @@ For more information about the governance of the Node.js project, see **Kunal Pathak** <kunal.pathak@microsoft.com> * [lance](https://github.com/lance) - **Lance Ball** <lball@redhat.com> -* [lucamaraschi](https://github.com/lucamaraschi) - -**Luca Maraschi** <luca.maraschi@gmail.com> (he/him) +* [Leko](https://github.com/Leko) - +**Shingo Inoue** <leko.noor@gmail.com> (he/him) * [lpinca](https://github.com/lpinca) - **Luigi Pinca** <luigipinca@gmail.com> (he/him) * [lucamaraschi](https://github.com/lucamaraschi) - @@ -500,6 +500,8 @@ For more information about the governance of the Node.js project, see **Rich Trott** <rtrott@gmail.com> (he/him) * [tunniclm](https://github.com/tunniclm) - **Mike Tunnicliffe** <m.j.tunnicliffe@gmail.com> +* [vdeturckheim](https://github.com/vdeturckheim) - +**Vladimir de Turckheim** <vlad2t@hotmail.com> (he/him) * [vkurchatkin](https://github.com/vkurchatkin) - **Vladimir Kurchatkin** <vladimir.kurchatkin@gmail.com> * [vsemozhetbyt](https://github.com/vsemozhetbyt) - diff --git a/doc/api/assert.md b/doc/api/assert.md index 779c6cd205ec91..b18ddc8e3c58a7 100644 --- a/doc/api/assert.md +++ b/doc/api/assert.md @@ -254,6 +254,8 @@ argument in callbacks. ```js const assert = require('assert'); +assert.ifError(null); +// OK assert.ifError(0); // OK assert.ifError(1); diff --git a/doc/api/buffer.md b/doc/api/buffer.md index 835295763ea876..9583fa15949fd2 100644 --- a/doc/api/buffer.md +++ b/doc/api/buffer.md @@ -1442,7 +1442,7 @@ endian format (`readDoubleBE()` returns big endian, `readDoubleLE()` returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -1479,7 +1479,7 @@ endian format (`readFloatBE()` returns big endian, `readFloatLE()` returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -1513,7 +1513,7 @@ added: v0.5.0 Reads a signed 8-bit integer from `buf` at the specified `offset`. Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Integers read from a `Buffer` are interpreted as two's complement signed values. @@ -1548,7 +1548,7 @@ the specified endian format (`readInt16BE()` returns big endian, `readInt16LE()` returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Integers read from a `Buffer` are interpreted as two's complement signed values. @@ -1583,7 +1583,7 @@ the specified endian format (`readInt32BE()` returns big endian, `readInt32LE()` returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Integers read from a `Buffer` are interpreted as two's complement signed values. @@ -1621,7 +1621,7 @@ and interprets the result as a two's complement signed value. Supports up to 48 bits of accuracy. Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -1650,7 +1650,7 @@ added: v0.5.0 Reads an unsigned 8-bit integer from `buf` at the specified `offset`. Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -1683,7 +1683,7 @@ specified endian format (`readUInt16BE()` returns big endian, `readUInt16LE()` returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -1722,7 +1722,7 @@ specified endian format (`readUInt32BE()` returns big endian, `readUInt32LE()` returns little endian). Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -1758,7 +1758,7 @@ and interprets the result as an unsigned integer. Supports up to 48 bits of accuracy. Setting `noAssert` to `true` allows `offset` to be beyond the end of `buf`, but -the result should be considered undefined behavior. +the resulting behavior is undefined. Examples: @@ -2083,7 +2083,7 @@ endian). `value` *should* be a valid 64-bit double. Behavior is undefined when `value` is anything other than a 64-bit double. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: @@ -2119,7 +2119,7 @@ endian). `value` *should* be a valid 32-bit float. Behavior is undefined when `value` is anything other than a 32-bit float. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: @@ -2153,7 +2153,7 @@ signed 8-bit integer. Behavior is undefined when `value` is anything other than a signed 8-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. `value` is interpreted and written as a two's complement signed integer. @@ -2187,7 +2187,7 @@ endian). `value` *should* be a valid signed 16-bit integer. Behavior is undefine when `value` is anything other than a signed 16-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. `value` is interpreted and written as a two's complement signed integer. @@ -2221,7 +2221,7 @@ endian). `value` *should* be a valid signed 32-bit integer. Behavior is undefine when `value` is anything other than a signed 32-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. `value` is interpreted and written as a two's complement signed integer. @@ -2256,7 +2256,7 @@ Supports up to 48 bits of accuracy. Behavior is undefined when `value` is anything other than a signed integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: @@ -2290,7 +2290,7 @@ valid unsigned 8-bit integer. Behavior is undefined when `value` is anything other than an unsigned 8-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: @@ -2324,7 +2324,7 @@ endian). `value` should be a valid unsigned 16-bit integer. Behavior is undefined when `value` is anything other than an unsigned 16-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: @@ -2362,7 +2362,7 @@ endian). `value` should be a valid unsigned 32-bit integer. Behavior is undefined when `value` is anything other than an unsigned 32-bit integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: @@ -2400,7 +2400,7 @@ Supports up to 48 bits of accuracy. Behavior is undefined when `value` is anything other than an unsigned integer. Setting `noAssert` to `true` allows the encoded form of `value` to extend beyond -the end of `buf`, but the result should be considered undefined behavior. +the end of `buf`, but the resulting behavior is undefined. Examples: diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 06fad013ef508f..b55bd0fea1d874 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -974,10 +974,10 @@ process.send({ foo: 'bar' }); Child Node.js processes will have a [`process.send()`][] method of their own that allows the child to send messages back to the parent. -There is a special case when sending a `{cmd: 'NODE_foo'}` message. All messages -containing a `NODE_` prefix in its `cmd` property are considered to be reserved -for use within Node.js core and will not be emitted in the child's -[`process.on('message')`][] event. Rather, such messages are emitted using the +There is a special case when sending a `{cmd: 'NODE_foo'}` message. Messages +containing a `NODE_` prefix in the `cmd` property are reserved for use within +Node.js core and will not be emitted in the child's [`process.on('message')`][] +event. Rather, such messages are emitted using the `process.on('internalMessage')` event and are consumed internally by Node.js. Applications should avoid using such messages or listening for `'internalMessage'` events as it is subject to change without notice. diff --git a/doc/api/crypto.md b/doc/api/crypto.md index 76b046ebe5a206..5f8de17b0b9ff7 100644 --- a/doc/api/crypto.md +++ b/doc/api/crypto.md @@ -1099,7 +1099,7 @@ password always creates the same key. The low iteration count and non-cryptographically secure hash algorithm allow passwords to be tested very rapidly. -In line with OpenSSL's recommendation to use pbkdf2 instead of +In line with OpenSSL's recommendation to use PBKDF2 instead of [`EVP_BytesToKey`][] it is recommended that developers derive a key and IV on their own using [`crypto.pbkdf2()`][] and to use [`crypto.createCipheriv()`][] to create the `Cipher` object. Users should not use ciphers with counter mode @@ -1154,7 +1154,7 @@ password always creates the same key. The low iteration count and non-cryptographically secure hash algorithm allow passwords to be tested very rapidly. -In line with OpenSSL's recommendation to use pbkdf2 instead of +In line with OpenSSL's recommendation to use PBKDF2 instead of [`EVP_BytesToKey`][] it is recommended that developers derive a key and IV on their own using [`crypto.pbkdf2()`][] and to use [`crypto.createDecipheriv()`][] to create the `Decipher` object. diff --git a/doc/api/http.md b/doc/api/http.md index a747518a9323e7..9860f0949d3987 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -550,7 +550,7 @@ Once a socket is assigned to this request and is connected added: v0.5.9 --> -* `timeout` {number} Milliseconds before a request is considered to be timed out. +* `timeout` {number} Milliseconds before a request times out. * `callback` {Function} Optional function to be called when a timeout occurs. Same as binding to the `timeout` event. Once a socket is assigned to this request and is connected diff --git a/doc/api/process.md b/doc/api/process.md index 4d0745491de2a3..c9aebfa8d2cce4 100644 --- a/doc/api/process.md +++ b/doc/api/process.md @@ -1300,6 +1300,19 @@ event loop **before** additional I/O is processed. As a result, recursively setting nextTick callbacks will block any I/O from happening, just like a `while(true);` loop. +## process.noDeprecation + + +* {boolean} + +The `process.noDeprecation` property indicates whether the `--no-deprecation` +flag is set on the current Node.js process. See the documentation for +the [`warning` event][process_warning] and the +[`emitWarning` method][process_emit_warning] for more information about this +flag's behavior. + ## process.pid + +* {boolean} + +The `process.throwDeprecation` property indicates whether the +`--throw-deprecation` flag is set on the current Node.js process. See the +documentation for the [`warning` event][process_warning] and the +[`emitWarning` method][process_emit_warning] for more information about this +flag's behavior. + ## process.title + +* {boolean} + +The `process.traceDeprecation` property indicates whether the +`--trace-deprecation` flag is set on the current Node.js process. See the +documentation for the [`warning` event][process_warning] and the +[`emitWarning` method][process_emit_warning] for more information about this +flag's behavior. + ## process.umask([mask]) -* `socket` {net.Socket} An instance of [`net.Socket`][] +* `socket` {net.Socket|stream.Duplex} + On the server side, any `Duplex` stream. On the client side, any + instance of [`net.Socket`][] (for generic `Duplex` stream support + on the client side, [`tls.connect()`][] must be used). * `options` {Object} * `isServer`: The SSL/TLS protocol is asymmetrical, TLSSockets must know if they are to behave as a server or a client. If `true` the TLS socket will be @@ -788,10 +791,12 @@ changes: * `port` {number} Port the client should connect to. * `path` {string} Creates unix socket connection to path. If this option is specified, `host` and `port` are ignored. - * `socket` {net.Socket} Establish secure connection on a given socket rather - than creating a new socket. If this option is specified, `path`, `host` and - `port` are ignored. Usually, a socket is already connected when passed to - `tls.connect()`, but it can be connected later. Note that + * `socket` {stream.Duplex} Establish secure connection on a given socket + rather than creating a new socket. Typically, this is an instance of + [`net.Socket`][], but any `Duplex` stream is allowed. + If this option is specified, `path`, `host` and `port` are ignored, + except for certificate validation. Usually, a socket is already connected + when passed to `tls.connect()`, but it can be connected later. Note that connection/disconnection/destruction of `socket` is the user's responsibility, calling `tls.connect()` will not cause `net.connect()` to be called. diff --git a/doc/guides/maintaining-V8.md b/doc/guides/maintaining-V8.md index 1e525809a04abc..6211cb887861b4 100644 --- a/doc/guides/maintaining-V8.md +++ b/doc/guides/maintaining-V8.md @@ -23,8 +23,7 @@ For example, at the time of this writing: * **Beta**: V8 5.5 is currently in beta. It will be promoted to stable next; approximately 6 weeks after V8 5.4 shipped as stable. * **Master**: V8 tip-of-tree corresponds to V8 5.6. This branch gets regularly released as part of the Chromium **canary** builds. This branch will be promoted to beta next when V8 5.5 ships as stable. -All older branches are considered **abandoned**, and are not maintained by the -V8 team. +All older branches are abandoned and are not maintained by the V8 team. ## V8 merge process overview @@ -131,9 +130,10 @@ includes the following branches1: -The versions of V8 used in Node.js v4.x and v6.x have already been abandoned by -upstream V8. However, Node.js needs to continue supporting these branches for -many months (Current branches) or several years (LTS branches). +The versions of V8 used in Node.js v4.x, v6.x, and 8.x have already been +abandoned by upstream V8. However, Node.js needs to continue supporting +these branches for many months (Current branches) or several +years (LTS branches). # Maintenance Process diff --git a/lib/.eslintrc.yaml b/lib/.eslintrc.yaml index aaebadca125814..437aa575645ad6 100644 --- a/lib/.eslintrc.yaml +++ b/lib/.eslintrc.yaml @@ -1,4 +1,6 @@ rules: + dot-notation: error + # Custom rules in tools/eslint-rules require-buffer: error buffer-constructor: error diff --git a/lib/_debugger.js b/lib/_debugger.js index 64a8b70c5e2e58..dd679c52c9e421 100644 --- a/lib/_debugger.js +++ b/lib/_debugger.js @@ -742,9 +742,9 @@ function Interface(stdin, stdout, args) { useGlobal: false, ignoreUndefined: true }; - if (parseInt(process.env['NODE_NO_READLINE'], 10)) { + if (parseInt(process.env.NODE_NO_READLINE, 10)) { opts.terminal = false; - } else if (parseInt(process.env['NODE_FORCE_READLINE'], 10)) { + } else if (parseInt(process.env.NODE_FORCE_READLINE, 10)) { opts.terminal = true; // Emulate Ctrl+C if we're emulating terminal @@ -754,7 +754,7 @@ function Interface(stdin, stdout, args) { }); } } - if (parseInt(process.env['NODE_DISABLE_COLORS'], 10)) { + if (parseInt(process.env.NODE_DISABLE_COLORS, 10)) { opts.useColors = false; } diff --git a/lib/_http_agent.js b/lib/_http_agent.js index c92242e38bf8c1..f11fa9fd6d2f5f 100644 --- a/lib/_http_agent.js +++ b/lib/_http_agent.js @@ -124,13 +124,8 @@ Agent.prototype.addRequest = function(req, options) { options = util._extend({}, options); options = util._extend(options, this.options); - if (!options.servername) { - options.servername = options.host; - const hostHeader = req.getHeader('host'); - if (hostHeader) { - options.servername = hostHeader.replace(/:.*$/, ''); - } - } + if (!options.servername) + options.servername = calculateServerName(options, req); var name = this.getName(options); if (!this.sockets[name]) { @@ -178,13 +173,8 @@ Agent.prototype.createSocket = function(req, options, cb) { options = util._extend({}, options); options = util._extend(options, self.options); - if (!options.servername) { - options.servername = options.host; - const hostHeader = req.getHeader('host'); - if (hostHeader) { - options.servername = hostHeader.replace(/:.*$/, ''); - } - } + if (!options.servername) + options.servername = calculateServerName(options, req); var name = self.getName(options); options._agentKey = name; @@ -211,6 +201,29 @@ Agent.prototype.createSocket = function(req, options, cb) { } }; +function calculateServerName(options, req) { + let servername = options.host; + const hostHeader = req.getHeader('host'); + if (hostHeader) { + // abc => abc + // abc:123 => abc + // [::1] => ::1 + // [::1]:123 => ::1 + if (hostHeader.startsWith('[')) { + const index = hostHeader.indexOf(']'); + if (index === -1) { + // Leading '[', but no ']'. Need to do something... + servername = hostHeader; + } else { + servername = hostHeader.substr(1, index - 1); + } + } else { + servername = hostHeader.split(':', 1)[0]; + } + } + return servername; +} + function installListeners(agent, s, options) { function onFree() { debug('CLIENT socket onFree'); diff --git a/lib/fs.js b/lib/fs.js index e6ab7ba6d6986d..5efccceb544d20 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -1919,7 +1919,8 @@ function ReadStream(path, options) { this.flags = options.flags === undefined ? 'r' : options.flags; this.mode = options.mode === undefined ? 0o666 : options.mode; - this.start = options.start; + this.start = typeof this.fd !== 'number' && options.start === undefined ? + 0 : options.start; this.end = options.end; this.autoClose = options.autoClose === undefined ? true : options.autoClose; this.pos = undefined; diff --git a/lib/internal/child_process.js b/lib/internal/child_process.js index 764cdd3cf26997..e01e19147bb6d1 100644 --- a/lib/internal/child_process.js +++ b/lib/internal/child_process.js @@ -383,7 +383,7 @@ ChildProcess.prototype.kill = function(sig) { if (sig === 0) { signal = 0; } else if (!sig) { - signal = constants['SIGTERM']; + signal = constants.SIGTERM; } else { signal = constants[sig]; } diff --git a/lib/module.js b/lib/module.js index 3b258f051bd4ca..6ff174ead61629 100644 --- a/lib/module.js +++ b/lib/module.js @@ -639,7 +639,7 @@ Module._initPaths = function() { paths.unshift(path.resolve(homeDir, '.node_modules')); } - var nodePath = process.env['NODE_PATH']; + var nodePath = process.env.NODE_PATH; if (nodePath) { paths = nodePath.split(path.delimiter).filter(function(path) { return !!path; diff --git a/lib/path.js b/lib/path.js index a121f5bf7e0160..3639fc47e7fef9 100644 --- a/lib/path.js +++ b/lib/path.js @@ -30,19 +30,14 @@ function normalizeStringWin32(path, allowAboveRoot) { res.charCodeAt(res.length - 1) !== 46/*.*/ || res.charCodeAt(res.length - 2) !== 46/*.*/) { if (res.length > 2) { - const start = res.length - 1; - var j = start; - for (; j >= 0; --j) { - if (res.charCodeAt(j) === 92/*\*/) - break; - } - if (j !== start) { - if (j === -1) { + const lastSlashIndex = res.lastIndexOf('\\'); + if (lastSlashIndex !== res.length - 1) { + if (lastSlashIndex === -1) { res = ''; lastSegmentLength = 0; } else { - res = res.slice(0, j); - lastSegmentLength = j; + res = res.slice(0, lastSlashIndex); + lastSegmentLength = res.length - 1 - res.lastIndexOf('\\'); } lastSlash = i; dots = 0; @@ -103,19 +98,14 @@ function normalizeStringPosix(path, allowAboveRoot) { res.charCodeAt(res.length - 1) !== 46/*.*/ || res.charCodeAt(res.length - 2) !== 46/*.*/) { if (res.length > 2) { - const start = res.length - 1; - var j = start; - for (; j >= 0; --j) { - if (res.charCodeAt(j) === 47/*/*/) - break; - } - if (j !== start) { - if (j === -1) { + const lastSlashIndex = res.lastIndexOf('/'); + if (lastSlashIndex !== res.length - 1) { + if (lastSlashIndex === -1) { res = ''; lastSegmentLength = 0; } else { - res = res.slice(0, j); - lastSegmentLength = j; + res = res.slice(0, lastSlashIndex); + lastSegmentLength = res.length - 1 - res.lastIndexOf('/'); } lastSlash = i; dots = 0; diff --git a/lib/tls.js b/lib/tls.js index c2a19d56e5e0e3..3c98e7a481e7ba 100644 --- a/lib/tls.js +++ b/lib/tls.js @@ -7,6 +7,7 @@ const net = require('net'); const url = require('url'); const binding = process.binding('crypto'); const Buffer = require('buffer').Buffer; +const canonicalizeIP = process.binding('cares_wrap').canonicalizeIP; // Allow {CLIENT_RENEG_LIMIT} client-initiated session renegotiations // every {CLIENT_RENEG_WINDOW} seconds. An error event is emitted if more @@ -156,7 +157,7 @@ exports.checkServerIdentity = function checkServerIdentity(host, cert) { const uri = url.parse(name.slice(4)); uriNames.push(uri.hostname); // TODO(bnoordhuis) Also use scheme. } else if (name.startsWith('IP Address:')) { - ips.push(name.slice(11)); + ips.push(canonicalizeIP(name.slice(11))); } } } @@ -165,7 +166,7 @@ exports.checkServerIdentity = function checkServerIdentity(host, cert) { let reason = 'Unknown reason'; if (net.isIP(host)) { - valid = ips.includes(host); + valid = ips.includes(canonicalizeIP(host)); if (!valid) reason = `IP: ${host} is not in the cert's list: ${ips.join(', ')}`; // TODO(bnoordhuis) Also check URI SANs that are IP addresses. diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc index 5290af2c24c959..b6c51be1b98171 100644 --- a/src/cares_wrap.cc +++ b/src/cares_wrap.cc @@ -1281,6 +1281,28 @@ static void IsIPv6(const FunctionCallbackInfo& args) { } } + +void CanonicalizeIP(const FunctionCallbackInfo& args) { + v8::Isolate* isolate = args.GetIsolate(); + node::Utf8Value ip(isolate, args[0]); + char address_buffer[sizeof(struct in6_addr)]; + char canonical_ip[INET6_ADDRSTRLEN]; + + int af; + if (uv_inet_pton(AF_INET, *ip, &address_buffer) == 0) + af = AF_INET; + else if (uv_inet_pton(AF_INET6, *ip, &address_buffer) == 0) + af = AF_INET6; + else + return; + + int err = uv_inet_ntop(af, address_buffer, canonical_ip, + sizeof(canonical_ip)); + CHECK_EQ(err, 0); + + args.GetReturnValue().Set(String::NewFromUtf8(isolate, canonical_ip)); +} + static void GetAddrInfo(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); @@ -1514,6 +1536,7 @@ static void Initialize(Local target, env->SetMethod(target, "isIP", IsIP); env->SetMethod(target, "isIPv4", IsIPv4); env->SetMethod(target, "isIPv6", IsIPv6); + env->SetMethod(target, "canonicalizeIP", CanonicalizeIP); env->SetMethod(target, "strerror", StrError); env->SetMethod(target, "getServers", GetServers); diff --git a/test/.eslintrc.yaml b/test/.eslintrc.yaml index 6d2c0ec90d22b0..792c62a7258db8 100644 --- a/test/.eslintrc.yaml +++ b/test/.eslintrc.yaml @@ -8,6 +8,7 @@ rules: # Custom rules in tools/eslint-rules prefer-common-mustnotcall: 2 + number-isnan: error ## common module is mandatory in tests required-modules: [error, common] diff --git a/test/known_issues/test-http-path-contains-unicode.js b/test/known_issues/test-http-path-contains-unicode.js index 68b66b7c6940ed..4d50c8865ba542 100644 --- a/test/known_issues/test-http-path-contains-unicode.js +++ b/test/known_issues/test-http-path-contains-unicode.js @@ -10,11 +10,7 @@ const http = require('http'); const expected = '/café🐶'; -assert.strictEqual( - expected, - '/caf\u{e9}\u{1f436}', - 'Sanity check that string literal produced the expected string' -); +assert.strictEqual('/caf\u{e9}\u{1f436}', expected); const server = http.createServer(common.mustCall(function(req, res) { assert.strictEqual(req.url, expected); diff --git a/test/message/error_exit.js b/test/message/error_exit.js index 1cb785a1b543a6..0312a41023c4d9 100644 --- a/test/message/error_exit.js +++ b/test/message/error_exit.js @@ -3,7 +3,7 @@ require('../common'); const assert = require('assert'); process.on('exit', function(code) { - console.error('Exiting with code=%d', code); + console.error(`Exiting with code=${code}`); }); assert.strictEqual(1, 2); diff --git a/test/message/max_tick_depth.js b/test/message/max_tick_depth.js index c433c0bab3f100..2f26e98ac76f77 100644 --- a/test/message/max_tick_depth.js +++ b/test/message/max_tick_depth.js @@ -4,7 +4,7 @@ require('../common'); process.maxTickDepth = 10; let i = 20; process.nextTick(function f() { - console.error('tick %d', i); + console.error(`tick ${i}`); if (i-- > 0) process.nextTick(f); }); diff --git a/test/parallel/test-cluster-net-send.js b/test/parallel/test-cluster-net-send.js index 73442bd4594a9f..068be0ec1df48d 100644 --- a/test/parallel/test-cluster-net-send.js +++ b/test/parallel/test-cluster-net-send.js @@ -5,7 +5,7 @@ const fork = require('child_process').fork; const net = require('net'); if (process.argv[2] !== 'child') { - console.error('[%d] master', process.pid); + console.error(`[${process.pid}] master`); const worker = fork(__filename, ['child']); let called = false; @@ -29,7 +29,7 @@ if (process.argv[2] !== 'child') { assert.ok(called); }); } else { - console.error('[%d] worker', process.pid); + console.error(`[${process.pid}] worker`); let socket; let cbcalls = 0; diff --git a/test/parallel/test-domain-http-server.js b/test/parallel/test-domain-http-server.js index 68573045e72b76..06d8ce577899c2 100644 --- a/test/parallel/test-domain-http-server.js +++ b/test/parallel/test-domain-http-server.js @@ -41,7 +41,7 @@ server.listen(0, next); function next() { const port = this.address().port; - console.log('listening on localhost:%d', port); + console.log(`listening on localhost:${port}`); let requests = 0; let responses = 0; @@ -66,7 +66,7 @@ function next() { dom.add(req); req.on('response', function(res) { responses++; - console.error('requests=%d responses=%d', requests, responses); + console.error(`requests=${requests} responses=${responses}`); if (responses === requests) { console.error('done, closing server'); // no more coming. diff --git a/test/parallel/test-env-var-no-warnings.js b/test/parallel/test-env-var-no-warnings.js index f829443888bc07..ff0421c46858ff 100644 --- a/test/parallel/test-env-var-no-warnings.js +++ b/test/parallel/test-env-var-no-warnings.js @@ -6,7 +6,8 @@ const cp = require('child_process'); if (process.argv[2] === 'child') { process.emitWarning('foo'); } else { - function test(env) { + function test(newEnv) { + const env = Object.assign({}, process.env, newEnv); const cmd = `"${process.execPath}" "${__filename}" child`; cp.exec(cmd, { env }, common.mustCall((err, stdout, stderr) => { diff --git a/test/parallel/test-eslint-number-isnan.js b/test/parallel/test-eslint-number-isnan.js new file mode 100644 index 00000000000000..deeac48bcccb68 --- /dev/null +++ b/test/parallel/test-eslint-number-isnan.js @@ -0,0 +1,20 @@ +'use strict'; + +require('../common'); + +const RuleTester = require('../../tools/eslint').RuleTester; +const rule = require('../../tools/eslint-rules/number-isnan'); + +const message = 'Please use Number.isNaN instead of the global isNaN function'; + +new RuleTester().run('number-isnan', rule, { + valid: [ + 'Number.isNaN()' + ], + invalid: [ + { + code: 'isNaN()', + errors: [{ message }] + } + ] +}); diff --git a/test/parallel/test-file-write-stream2.js b/test/parallel/test-file-write-stream2.js index 1d11f6de3e96ec..eae9fedbc1e7fc 100644 --- a/test/parallel/test-file-write-stream2.js +++ b/test/parallel/test-file-write-stream2.js @@ -20,8 +20,8 @@ process.on('exit', function() { removeTestFile(); if (cb_occurred !== cb_expected) { console.log(' Test callback events missing or out of order:'); - console.log(' expected: %j', cb_expected); - console.log(' occurred: %j', cb_occurred); + console.log(` expected: ${cb_expected}`); + console.log(` occurred: ${cb_occurred}`); assert.strictEqual( cb_occurred, cb_expected, `events missing or out of order: "${cb_occurred}" !== "${cb_expected}"`); @@ -57,7 +57,7 @@ file.on('drain', function() { if (countDrains === 1) { console.error('drain=1, write again'); assert.strictEqual(fs.readFileSync(filepath, 'utf8'), EXPECTED); - console.error('ondrain write ret=%j', file.write(EXPECTED)); + console.error(`ondrain write ret= ${file.write(EXPECTED)}`); cb_occurred += 'write '; } else if (countDrains === 2) { console.error('second drain, end'); @@ -81,7 +81,7 @@ file.on('error', function(err) { for (let i = 0; i < 11; i++) { const ret = file.write(String(i)); - console.error('%d %j', i, ret); + console.error(`${i} ${ret}`); // return false when i hits 10 assert.strictEqual(ret, i !== 10); diff --git a/test/parallel/test-file-write-stream3.js b/test/parallel/test-file-write-stream3.js index 8550cd0305ae4b..169beff5d898ed 100644 --- a/test/parallel/test-file-write-stream3.js +++ b/test/parallel/test-file-write-stream3.js @@ -21,8 +21,8 @@ const fileDataExpected_3 = 'abcdefghij\u2026\u2026qrstuvwxyz'; process.on('exit', function() { if (cb_occurred !== cb_expected) { console.log(' Test callback events missing or out of order:'); - console.log(' expected: %j', cb_expected); - console.log(' occurred: %j', cb_occurred); + console.log(` expected: ${cb_expected}`); + console.log(` occurred: ${cb_occurred}`); assert.strictEqual( cb_occurred, cb_expected, `events missing or out of order: "${cb_occurred}" !== "${cb_expected}"`); diff --git a/test/parallel/test-fs-read-stream-fd-leak.js b/test/parallel/test-fs-read-stream-fd-leak.js index 28ec7b91b4c35b..5bf0157ff4e7ae 100644 --- a/test/parallel/test-fs-read-stream-fd-leak.js +++ b/test/parallel/test-fs-read-stream-fd-leak.js @@ -24,7 +24,7 @@ fs.close = function() { }; function testLeak(endFn, callback) { - console.log('testing for leaks from fs.createReadStream().%s()...', endFn); + console.log(`testing for leaks from fs.createReadStream().${endFn}()...`); let i = 0; let check = 0; diff --git a/test/parallel/test-fs-read-stream.js b/test/parallel/test-fs-read-stream.js index bab809f72c19ce..95d5fbeaef9973 100644 --- a/test/parallel/test-fs-read-stream.js +++ b/test/parallel/test-fs-read-stream.js @@ -132,6 +132,20 @@ stream.on('end', function() { assert.strictEqual('x', stream.data); }); +{ + // Verify that end works when start is not specified. + const stream = new fs.createReadStream(rangeFile, { end: 1 }); + stream.data = ''; + + stream.on('data', function(chunk) { + stream.data += chunk; + }); + + stream.on('end', common.mustCall(function() { + assert.strictEqual('xy', stream.data); + })); +} + // pause and then resume immediately. const pauseRes = fs.createReadStream(rangeFile); pauseRes.pause(); diff --git a/test/parallel/test-fs-write-string-coerce.js b/test/parallel/test-fs-write-string-coerce.js index e257dfc0c73ee0..ec6f098fa691eb 100644 --- a/test/parallel/test-fs-write-string-coerce.js +++ b/test/parallel/test-fs-write-string-coerce.js @@ -19,8 +19,8 @@ fs.open(fn, 'w', 0o644, common.mustCall(function(err, fd) { assert.strictEqual(Buffer.byteLength(expected), written); fs.closeSync(fd); const found = fs.readFileSync(fn, 'utf8'); - console.log('expected: "%s"', expected); - console.log('found: "%s"', found); + console.log(`expected: "${expected}"`); + console.log(`found: "${found}"`); fs.unlinkSync(fn); assert.strictEqual(expected, found); })); diff --git a/test/parallel/test-http-client-timeout-agent.js b/test/parallel/test-http-client-timeout-agent.js index 55c7d39ab4eec7..de710f4ee10017 100644 --- a/test/parallel/test-http-client-timeout-agent.js +++ b/test/parallel/test-http-client-timeout-agent.js @@ -69,7 +69,7 @@ server.listen(0, options.host, function() { }); process.on('exit', function() { - console.error('done=%j sent=%j', requests_done, requests_sent); + console.error(`done=${requests_done} sent=${requests_sent}`); assert.strictEqual(requests_done, requests_sent, 'timeout on http request called too much'); }); diff --git a/test/parallel/test-http-outgoing-finish.js b/test/parallel/test-http-outgoing-finish.js index 3ed9c5090b7f9f..f4b12be831abd5 100644 --- a/test/parallel/test-http-outgoing-finish.js +++ b/test/parallel/test-http-outgoing-finish.js @@ -37,19 +37,19 @@ function write(out) { // that 'finish' isn't emitted until the stream is fully flushed. out.on('finish', function() { finishEvent = true; - console.error('%s finish event', name); + console.error(`${name} finish event`); process.nextTick(function() { assert(endCb, `${name} got finish event before endcb!`); - console.log('ok - %s finishEvent', name); + console.log(`ok - ${name} finishEvent`); }); }); out.end(buf, function() { endCb = true; - console.error('%s endCb', name); + console.error(`${name} endCb`); process.nextTick(function() { assert(finishEvent, `${name} got endCb event before finishEvent!`); - console.log('ok - %s endCb', name); + console.log(`ok - ${name} endCb`); }); }); } diff --git a/test/parallel/test-http-response-status-message.js b/test/parallel/test-http-response-status-message.js index 0c3d329ff57fdd..e0ffb2a045a98a 100644 --- a/test/parallel/test-http-response-status-message.js +++ b/test/parallel/test-http-response-status-message.js @@ -3,8 +3,7 @@ require('../common'); const assert = require('assert'); const http = require('http'); const net = require('net'); - -let testsComplete = 0; +const Countdown = require('../common/countdown'); const testCases = [ { path: '/200', statusMessage: 'OK', @@ -38,6 +37,8 @@ const server = net.createServer(function(connection) { }); }); +const countdown = new Countdown(testCases.length, () => server.close()); + function runTest(testCaseIndex) { const testCase = testCases[testCaseIndex]; @@ -50,12 +51,9 @@ function runTest(testCaseIndex) { assert.strictEqual(testCase.statusMessage, response.statusMessage); response.on('end', function() { - testsComplete++; - + countdown.dec(); if (testCaseIndex + 1 < testCases.length) { runTest(testCaseIndex + 1); - } else { - server.close(); } }); @@ -64,7 +62,3 @@ function runTest(testCaseIndex) { } server.listen(0, function() { runTest(0); }); - -process.on('exit', function() { - assert.strictEqual(testCases.length, testsComplete); -}); diff --git a/test/parallel/test-listen-fd-cluster.js b/test/parallel/test-listen-fd-cluster.js index 10f8128938a188..c2bfba3da9b408 100644 --- a/test/parallel/test-listen-fd-cluster.js +++ b/test/parallel/test-listen-fd-cluster.js @@ -64,7 +64,7 @@ function test(cb) { conn.end('hello from parent\n'); }).listen(0, function() { const port = this.address().port; - console.error('server listening on %d', port); + console.error(`server listening on ${port}`); const spawn = require('child_process').spawn; const master = spawn(process.execPath, [__filename, 'master'], { diff --git a/test/parallel/test-net-server-max-connections.js b/test/parallel/test-net-server-max-connections.js index f560a7dafc4446..76d307c2c535fb 100644 --- a/test/parallel/test-net-server-max-connections.js +++ b/test/parallel/test-net-server-max-connections.js @@ -34,7 +34,7 @@ function makeConnection(index) { } c.on('close', function() { - console.error('closed %d', index); + console.error(`closed ${index}`); closes++; if (closes < N / 2) { @@ -76,7 +76,7 @@ function makeConnection(index) { if (common.isSunOS && (e.code === 'ECONNREFUSED')) { c.connect(server.address().port); } - console.error('error %d: %s', index, e); + console.error(`error ${index}: ${e}`); }); } diff --git a/test/parallel/test-path-normalize.js b/test/parallel/test-path-normalize.js index 0820052446367e..0dd1b8339f4c64 100644 --- a/test/parallel/test-path-normalize.js +++ b/test/parallel/test-path-normalize.js @@ -27,6 +27,18 @@ assert.strictEqual(path.win32.normalize('..\\foo..\\..\\..\\bar'), '..\\..\\bar'); assert.strictEqual(path.win32.normalize('..\\...\\..\\.\\...\\..\\..\\bar'), '..\\..\\bar'); +assert.strictEqual(path.win32.normalize('../../../foo/../../../bar'), + '..\\..\\..\\..\\..\\bar'); +assert.strictEqual(path.win32.normalize('../../../foo/../../../bar/../../'), + '..\\..\\..\\..\\..\\..\\'); +assert.strictEqual( + path.win32.normalize('../foobar/barfoo/foo/../../../bar/../../'), + '..\\..\\' +); +assert.strictEqual( + path.win32.normalize('../.../../foobar/../../../bar/../../baz'), + '..\\..\\..\\..\\baz' +); assert.strictEqual(path.posix.normalize('./fixtures///b/../b/c.js'), 'fixtures/b/c.js'); @@ -44,3 +56,15 @@ assert.strictEqual(path.posix.normalize('bar/foo..'), 'bar/foo..'); assert.strictEqual(path.posix.normalize('../foo../../../bar'), '../../bar'); assert.strictEqual(path.posix.normalize('../.../.././.../../../bar'), '../../bar'); +assert.strictEqual(path.posix.normalize('../../../foo/../../../bar'), + '../../../../../bar'); +assert.strictEqual(path.posix.normalize('../../../foo/../../../bar/../../'), + '../../../../../../'); +assert.strictEqual( + path.posix.normalize('../foobar/barfoo/foo/../../../bar/../../'), + '../../' +); +assert.strictEqual( + path.posix.normalize('../.../../foobar/../../../bar/../../baz'), + '../../../../baz' +); diff --git a/test/parallel/test-process-exit-code.js b/test/parallel/test-process-exit-code.js index 11e00152fdf011..99f8368903bb7f 100644 --- a/test/parallel/test-process-exit-code.js +++ b/test/parallel/test-process-exit-code.js @@ -72,7 +72,7 @@ function parent() { assert.strictEqual( code, exit, `wrong exit for ${arg}\nexpected:${exit} but got:${code}`); - console.log('ok - %s exited with %d', arg, exit); + console.log(`ok - ${arg} exited with ${exit}`); }); }; diff --git a/test/parallel/test-punycode.js b/test/parallel/test-punycode.js index 1d81fe339f808c..7e457255017efd 100644 --- a/test/parallel/test-punycode.js +++ b/test/parallel/test-punycode.js @@ -179,10 +179,7 @@ const tests = [ let errors = 0; const handleError = (error, name) => { console.error( - 'FAIL: %s expected %j, got %j', - name, - error.expected, - error.actual + `FAIL: ${name} expected ${error.expected}, got ${error.actual}` ); errors++; }; diff --git a/test/parallel/test-readdouble.js b/test/parallel/test-readdouble.js index 00340a39e631c0..517393643f2804 100644 --- a/test/parallel/test-readdouble.js +++ b/test/parallel/test-readdouble.js @@ -51,12 +51,12 @@ function test(clazz) { buffer[5] = 0xff; buffer[6] = 0x0f; buffer[7] = 0x00; - assert.ok(isNaN(buffer.readDoubleBE(0))); + assert.ok(Number.isNaN(buffer.readDoubleBE(0))); assert.strictEqual(2.225073858507201e-308, buffer.readDoubleLE(0)); buffer[6] = 0xef; buffer[7] = 0x7f; - assert.ok(isNaN(buffer.readDoubleBE(0))); + assert.ok(Number.isNaN(buffer.readDoubleBE(0))); assert.strictEqual(1.7976931348623157e+308, buffer.readDoubleLE(0)); buffer[0] = 0; diff --git a/test/parallel/test-repl-syntax-error-handling.js b/test/parallel/test-repl-syntax-error-handling.js index c56c45dc6b90ae..36b86f100459ae 100644 --- a/test/parallel/test-repl-syntax-error-handling.js +++ b/test/parallel/test-repl-syntax-error-handling.js @@ -17,7 +17,7 @@ function parent() { child.stderr.setEncoding('utf8'); child.stderr.on('data', function(c) { - console.error('%j', c); + console.error(`${c}`); throw new Error('should not get stderr data'); }); diff --git a/test/parallel/test-stream-unshift-read-race.js b/test/parallel/test-stream-unshift-read-race.js index 90d1539b525344..8f0890c6190866 100644 --- a/test/parallel/test-stream-unshift-read-race.js +++ b/test/parallel/test-stream-unshift-read-race.js @@ -82,9 +82,9 @@ w.on('finish', common.mustCall(function() { // lacking that piece. assert.strictEqual(written[0], 'asdfasdfas'); let asdf = 'd'; - console.error('0: %s', written[0]); + console.error(`0: ${written[0]}`); for (let i = 1; i < written.length; i++) { - console.error('%s: %s', i.toString(32), written[i]); + console.error(`${i.toString(32)}: ${written[i]}`); assert.strictEqual(written[i].slice(0, 4), '1234'); for (let j = 4; j < written[i].length; j++) { const c = written[i].charAt(j); diff --git a/test/parallel/test-stream-writev.js b/test/parallel/test-stream-writev.js index d70a7d6819b74d..c7143d0e7f79c8 100644 --- a/test/parallel/test-stream-writev.js +++ b/test/parallel/test-stream-writev.js @@ -24,7 +24,7 @@ function run() { } function test(decode, uncork, multi, next) { - console.log('# decode=%j uncork=%j multi=%j', decode, uncork, multi); + console.log(`# decode=${decode} uncork=${uncork} multi=${multi}`); let counter = 0; let expectCount = 0; function cnt(msg) { diff --git a/test/parallel/test-stream2-large-read-stall.js b/test/parallel/test-stream2-large-read-stall.js index 2422747f820bc1..7c40c8fd294195 100644 --- a/test/parallel/test-stream2-large-read-stall.js +++ b/test/parallel/test-stream2-large-read-stall.js @@ -22,9 +22,9 @@ r.on('readable', function() { console.error('>> readable'); let ret; do { - console.error(' > read(%d)', READSIZE); + console.error(` > read(${READSIZE})`); ret = r.read(READSIZE); - console.error(' < %j (%d remain)', ret && ret.length, rs.length); + console.error(` < ${ret && ret.length} (${rs.length} remain)`); } while (ret && ret.length === READSIZE); console.error('<< after read()', @@ -47,7 +47,7 @@ function push() { return r.push(null); } - console.error(' push #%d', pushes); + console.error(` push #${pushes}`); if (r.push(Buffer.allocUnsafe(PUSHSIZE))) setTimeout(push, 1); } diff --git a/test/parallel/test-stream2-push.js b/test/parallel/test-stream2-push.js index 80315f2fb3f0cb..8fe7490b2b31a6 100644 --- a/test/parallel/test-stream2-push.js +++ b/test/parallel/test-stream2-push.js @@ -70,7 +70,7 @@ const expectWritten = 'asdfgasdfgasdfgasdfg' ]; writer._write = function(chunk, encoding, cb) { - console.error('WRITE %s', chunk); + console.error(`WRITE ${chunk}`); written.push(chunk); process.nextTick(cb); }; diff --git a/test/parallel/test-stream2-readable-non-empty-end.js b/test/parallel/test-stream2-readable-non-empty-end.js index 0df461eb5f2919..5b7d0ca51389a0 100644 --- a/test/parallel/test-stream2-readable-non-empty-end.js +++ b/test/parallel/test-stream2-readable-non-empty-end.js @@ -30,7 +30,7 @@ test.on('readable', function() { const res = test.read(b); if (res) { bytesread += res.length; - console.error('br=%d len=%d', bytesread, len); + console.error(`br=${bytesread} len=${len}`); setTimeout(next, 1); } test.read(0); diff --git a/test/parallel/test-stream3-pause-then-read.js b/test/parallel/test-stream3-pause-then-read.js index a1be563683c0a2..e4e850201986bc 100644 --- a/test/parallel/test-stream3-pause-then-read.js +++ b/test/parallel/test-stream3-pause-then-read.js @@ -39,7 +39,7 @@ function read100() { } function readn(n, then) { - console.error('read %d', n); + console.error(`read ${n}`); expectEndingData -= n; (function read() { const c = r.read(n); diff --git a/test/parallel/test-tls-canonical-ip.js b/test/parallel/test-tls-canonical-ip.js new file mode 100644 index 00000000000000..408948119c3501 --- /dev/null +++ b/test/parallel/test-tls-canonical-ip.js @@ -0,0 +1,31 @@ +'use strict'; +require('../common'); + +// Test conversion of IP addresses to the format returned +// for addresses in Subject Alternative Name section +// of a TLS certificate + +const assert = require('assert'); +const { canonicalizeIP } = process.binding('cares_wrap'); + +assert.strictEqual(canonicalizeIP('127.0.0.1'), '127.0.0.1'); +assert.strictEqual(canonicalizeIP('10.1.0.1'), '10.1.0.1'); +assert.strictEqual(canonicalizeIP('::1'), '::1'); +assert.strictEqual(canonicalizeIP('fe80:0:0:0:0:0:0:1'), 'fe80::1'); +assert.strictEqual(canonicalizeIP('fe80:0:0:0:0:0:0:0'), 'fe80::'); +assert.strictEqual(canonicalizeIP('fe80::0000:0010:0001'), 'fe80::10:1'); +assert.strictEqual(canonicalizeIP('0001:2222:3333:4444:5555:6666:7777:0088'), + '1:2222:3333:4444:5555:6666:7777:88'); + +assert.strictEqual(canonicalizeIP('0001:2222:3333:4444:5555:6666::'), + '1:2222:3333:4444:5555:6666::'); + +assert.strictEqual(canonicalizeIP('a002:B12:00Ba:4444:5555:6666:0:0'), + 'a002:b12:ba:4444:5555:6666::'); + +// IPv4 address represented in IPv6 +assert.strictEqual(canonicalizeIP('0:0:0:0:0:ffff:c0a8:101'), + '::ffff:192.168.1.1'); + +assert.strictEqual(canonicalizeIP('::ffff:192.168.1.1'), + '::ffff:192.168.1.1'); diff --git a/test/parallel/test-tls-client-getephemeralkeyinfo.js b/test/parallel/test-tls-client-getephemeralkeyinfo.js index a73f0fafd9dd6a..50848a420d57bc 100644 --- a/test/parallel/test-tls-client-getephemeralkeyinfo.js +++ b/test/parallel/test-tls-client-getephemeralkeyinfo.js @@ -6,7 +6,6 @@ const fixtures = require('../common/fixtures'); const assert = require('assert'); const tls = require('tls'); -const fs = require('fs'); const key = fixtures.readKey('agent2-key.pem'); const cert = fixtures.readKey('agent2-cert.pem'); @@ -15,9 +14,7 @@ let ntests = 0; let nsuccess = 0; function loadDHParam(n) { - let path = fixtures.fixturesDir; - if (n !== 'error') path += '/keys'; - return fs.readFileSync(`${path}/dh${n}.pem`); + return fixtures.readKey(`dh${n}.pem`); } const cipherlist = { diff --git a/test/parallel/test-tls-client-mindhsize.js b/test/parallel/test-tls-client-mindhsize.js index 51ea1f08b71c90..aab719ad44e4e3 100644 --- a/test/parallel/test-tls-client-mindhsize.js +++ b/test/parallel/test-tls-client-mindhsize.js @@ -14,10 +14,7 @@ let nsuccess = 0; let nerror = 0; function loadDHParam(n) { - const params = [`dh${n}.pem`]; - if (n !== 'error') - params.unshift('keys'); - return fixtures.readSync(params); + return fixtures.readKey(`dh${n}.pem`); } function test(size, err, next) { diff --git a/test/parallel/test-tls-client-verify.js b/test/parallel/test-tls-client-verify.js index 76af6d1ff09942..d06e89d437a0a0 100644 --- a/test/parallel/test-tls-client-verify.js +++ b/test/parallel/test-tls-client-verify.js @@ -122,6 +122,6 @@ runTest(0); process.on('exit', function() { - console.log('successful tests: %d', successfulTests); + console.log(`successful tests: ${successfulTests}`); assert.strictEqual(successfulTests, testCases.length); }); diff --git a/test/parallel/test-tls-env-bad-extra-ca.js b/test/parallel/test-tls-env-bad-extra-ca.js index 493b659778b2f2..f7e9341ad00757 100644 --- a/test/parallel/test-tls-env-bad-extra-ca.js +++ b/test/parallel/test-tls-env-bad-extra-ca.js @@ -16,10 +16,10 @@ if (process.env.CHILD) { return tls.createServer({}); } -const env = { +const env = Object.assign({}, process.env, { CHILD: 'yes', - NODE_EXTRA_CA_CERTS: `${fixtures.fixturesDir}/no-such-file-exists` -}; + NODE_EXTRA_CA_CERTS: `${fixtures.fixturesDir}/no-such-file-exists`, +}); const opts = { env: env, diff --git a/test/parallel/test-tls-env-extra-ca.js b/test/parallel/test-tls-env-extra-ca.js index 5f011f33382ac6..4dd12a78b6387c 100644 --- a/test/parallel/test-tls-env-extra-ca.js +++ b/test/parallel/test-tls-env-extra-ca.js @@ -32,11 +32,11 @@ const server = tls.createServer(options, common.mustCall(function(s) { s.end('bye'); server.close(); })).listen(0, common.mustCall(function() { - const env = { + const env = Object.assign({}, process.env, { CHILD: 'yes', PORT: this.address().port, NODE_EXTRA_CA_CERTS: fixtures.path('keys', 'ca1-cert.pem') - }; + }); fork(__filename, {env: env}).on('exit', common.mustCall(function(status) { assert.strictEqual(status, 0, 'client did not succeed in connecting'); diff --git a/test/parallel/test-tls-generic-stream.js b/test/parallel/test-tls-generic-stream.js new file mode 100644 index 00000000000000..d4e5427acae110 --- /dev/null +++ b/test/parallel/test-tls-generic-stream.js @@ -0,0 +1,38 @@ +'use strict'; +const common = require('../common'); +if (!common.hasCrypto) + common.skip('missing crypto'); + +const fixtures = require('../common/fixtures'); +const makeDuplexPair = require('../common/duplexpair'); +const assert = require('assert'); +const { TLSSocket, connect } = require('tls'); + +const key = fixtures.readKey('agent1-key.pem'); +const cert = fixtures.readKey('agent1-cert.pem'); +const ca = fixtures.readKey('ca1-cert.pem'); + +const { clientSide, serverSide } = makeDuplexPair(); + +const clientTLS = connect({ + socket: clientSide, + ca, + host: 'agent1' // Hostname from certificate +}); +const serverTLS = new TLSSocket(serverSide, { + isServer: true, + key, + cert, + ca +}); + +assert.strictEqual(clientTLS.connecting, false); +assert.strictEqual(serverTLS.connecting, false); + +clientTLS.on('secureConnect', common.mustCall(() => { + clientTLS.write('foobar', common.mustCall(() => { + assert.strictEqual(serverTLS.read().toString(), 'foobar'); + assert.strictEqual(clientTLS._handle.writeQueueSize, 0); + })); + assert.ok(clientTLS._handle.writeQueueSize > 0); +})); diff --git a/test/parallel/test-tls-pause.js b/test/parallel/test-tls-pause.js index 74d32a2a9bdb4e..371dd9e4a5b43f 100644 --- a/test/parallel/test-tls-pause.js +++ b/test/parallel/test-tls-pause.js @@ -36,7 +36,7 @@ server.listen(0, function() { function send() { console.error('sending'); const ret = client.write(Buffer.allocUnsafe(bufSize)); - console.error('write => %j', ret); + console.error(`write => ${ret}`); if (false !== ret) { console.error('write again'); sent += bufSize; diff --git a/test/parallel/test-tls-server-verify.js b/test/parallel/test-tls-server-verify.js index 609ac3ddc02afe..6f045235217ee8 100644 --- a/test/parallel/test-tls-server-verify.js +++ b/test/parallel/test-tls-server-verify.js @@ -238,7 +238,7 @@ function runTest(port, testIndex) { const tcase = testCases[testIndex]; if (!tcase) return; - console.error(`${prefix}Running '%s'`, tcase.title); + console.error(`${prefix}Running '${tcase.title}'`); const cas = tcase.CAs.map(loadPEM); diff --git a/test/parallel/test-writefloat.js b/test/parallel/test-writefloat.js index aeb62c8c022484..3ff240d9dad176 100644 --- a/test/parallel/test-writefloat.js +++ b/test/parallel/test-writefloat.js @@ -106,8 +106,8 @@ function test(clazz) { // Darwin ia32 does the other kind of NaN. // Compiler bug. No one really cares. assert(0x7F === buffer[7] || 0xFF === buffer[7]); - assert.ok(isNaN(buffer.readFloatBE(0))); - assert.ok(isNaN(buffer.readFloatLE(4))); + assert.ok(Number.isNaN(buffer.readFloatBE(0))); + assert.ok(Number.isNaN(buffer.readFloatLE(4))); } diff --git a/test/parallel/test-zlib.js b/test/parallel/test-zlib.js index 1086be6daf320f..b06b773cf44a7b 100644 --- a/test/parallel/test-zlib.js +++ b/test/parallel/test-zlib.js @@ -136,7 +136,7 @@ assert.doesNotThrow(() => { }, 'windowsBits set to 8 should follow legacy zlib behavior'); { - const node = fs.createReadStream(process.execPath); + const node = fs.createReadStream(fixtures.path('person.jpg')); const raw = []; const reinflated = []; node.on('data', (chunk) => raw.push(chunk)); diff --git a/test/pummel/test-exec.js b/test/pummel/test-exec.js index ebc32ce2689042..56c8d06c0681cd 100644 --- a/test/pummel/test-exec.js +++ b/test/pummel/test-exec.js @@ -58,7 +58,7 @@ exec('thisisnotavalidcommand', function(err, stdout, stderr) { const sleeperStart = new Date(); exec(SLEEP3_COMMAND, { timeout: 50 }, function(err, stdout, stderr) { const diff = (new Date()) - sleeperStart; - console.log('\'sleep 3\' with timeout 50 took %d ms', diff); + console.log(`'sleep 3' with timeout 50 took ${diff} ms`); assert.ok(diff < 500); assert.ok(err); assert.ok(err.killed); @@ -72,7 +72,7 @@ const startSleep3 = new Date(); const killMeTwice = exec(SLEEP3_COMMAND, {timeout: 1000}, killMeTwiceCallback); process.nextTick(function() { - console.log('kill pid %d', killMeTwice.pid); + console.log(`kill pid ${killMeTwice.pid}`); // make sure there is no race condition in starting the process // the PID SHOULD exist directly following the exec() call. assert.strictEqual('number', typeof killMeTwice._handle.pid); @@ -91,7 +91,7 @@ function killMeTwiceCallback(err, stdout, stderr) { assert.strictEqual(stderr, ''); // the timeout should still be in effect - console.log('\'sleep 3\' was already killed. Took %d ms', diff); + console.log(`'sleep 3' was already killed. Took ${diff} ms`); assert.ok(diff < 1500); } diff --git a/test/pummel/test-net-write-callbacks.js b/test/pummel/test-net-write-callbacks.js index 9bc4bc63c41a4e..3ea4413c00fc46 100644 --- a/test/pummel/test-net-write-callbacks.js +++ b/test/pummel/test-net-write-callbacks.js @@ -8,7 +8,7 @@ const N = 500000; const server = net.Server(function(socket) { socket.on('data', function(d) { - console.error('got %d bytes', d.length); + console.error(`got ${d.length} bytes`); }); socket.on('end', function() { diff --git a/test/pummel/test-regress-GH-892.js b/test/pummel/test-regress-GH-892.js index 34414672218b4b..f98643c46cd6a3 100644 --- a/test/pummel/test-regress-GH-892.js +++ b/test/pummel/test-regress-GH-892.js @@ -82,11 +82,11 @@ const server = https.Server(serverOptions, function(req, res) { }); server.listen(common.PORT, function() { - console.log('expecting %d bytes', bytesExpected); + console.log(`expecting ${bytesExpected} bytes`); makeRequest(); }); process.on('exit', function() { - console.error('got %d bytes', uploadCount); + console.error(`got ${uploadCount} bytes`); assert.strictEqual(uploadCount, bytesExpected); }); diff --git a/test/pummel/test-tls-throttle.js b/test/pummel/test-tls-throttle.js index 502b7306766264..d56021c2871e71 100644 --- a/test/pummel/test-tls-throttle.js +++ b/test/pummel/test-tls-throttle.js @@ -51,8 +51,8 @@ server.listen(common.PORT, function() { function displayCounts() { - console.log('body.length: %d', body.length); - console.log(' recvCount: %d', recvCount); + console.log(`body.length: ${body.length}`); + console.log(` recvCount: ${recvCount}`); } diff --git a/test/pummel/test-vm-memleak.js b/test/pummel/test-vm-memleak.js index 8bcd08b48606af..fb9a8655d266a9 100644 --- a/test/pummel/test-vm-memleak.js +++ b/test/pummel/test-vm-memleak.js @@ -36,6 +36,6 @@ function testContextLeak() { } process.on('exit', function() { - console.error('max mem: %dmb', Math.round(maxMem / (1024 * 1024))); + console.error(`max mem: ${Math.round(maxMem / (1024 * 1024))}mb`); assert.ok(maxMem < 64 * 1024 * 1024); }); diff --git a/test/sequential/test-require-cache-without-stat.js b/test/sequential/test-require-cache-without-stat.js index 021c86ccee0e25..8b698764786b45 100644 --- a/test/sequential/test-require-cache-without-stat.js +++ b/test/sequential/test-require-cache-without-stat.js @@ -31,7 +31,7 @@ require('../fixtures/a.js'); require('./../fixtures/a.js'); require('http'); -console.log('counterBefore = %d', counter); +console.log(`counterBefore = ${counter}`); const counterBefore = counter; // Now load the module a bunch of times with equivalent paths. @@ -47,7 +47,7 @@ for (let i = 0; i < 100; i++) { require('http'); } -console.log('counterAfter = %d', counter); +console.log(`counterAfter = ${counter}`); const counterAfter = counter; assert.strictEqual(counterBefore, counterAfter); diff --git a/test/sequential/test-stream2-stderr-sync.js b/test/sequential/test-stream2-stderr-sync.js index cfe77f1b4275e2..69e53845d8b8d2 100644 --- a/test/sequential/test-stream2-stderr-sync.js +++ b/test/sequential/test-stream2-stderr-sync.js @@ -17,7 +17,7 @@ function parent() { child.on('close', function() { assert.strictEqual(err, `child ${c}\nfoo\nbar\nbaz\n`); - console.log('ok %d child #%d', ++i, c); + console.log(`ok ${++i} child #${c}`); if (i === children.length) console.log(`1..${i}`); }); diff --git a/tools/doc/type-parser.js b/tools/doc/type-parser.js index ee50d48f61d45e..bfe058a42c2cd2 100644 --- a/tools/doc/type-parser.js +++ b/tools/doc/type-parser.js @@ -26,6 +26,7 @@ const typeMap = { 'Stream': 'stream.html#stream_stream', 'stream.Writable': 'stream.html#stream_class_stream_writable', 'stream.Readable': 'stream.html#stream_class_stream_readable', + 'stream.Duplex': 'stream.html#stream_class_stream_duplex', 'ChildProcess': 'child_process.html#child_process_class_childprocess', 'cluster.Worker': 'cluster.html#cluster_class_worker', 'dgram.Socket': 'dgram.html#dgram_class_dgram_socket', diff --git a/tools/eslint-rules/number-isnan.js b/tools/eslint-rules/number-isnan.js new file mode 100644 index 00000000000000..885c38be8b2384 --- /dev/null +++ b/tools/eslint-rules/number-isnan.js @@ -0,0 +1,14 @@ +'use strict'; + +const astSelector = "CallExpression[callee.name='isNaN']"; +const msg = 'Please use Number.isNaN instead of the global isNaN function'; + +module.exports = function(context) { + function report(node) { + context.report(node, msg); + } + + return { + [astSelector]: report + }; +};