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