diff --git a/BUILDING.md b/BUILDING.md index c459a867ba6..fbf6b9cd964 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -10,7 +10,7 @@ file a new issue. ## Supported platforms -This list of supported platforms is current as of the branch / release to +This list of supported platforms is current as of the branch/release to which it is attached. ### Input @@ -33,15 +33,15 @@ Support is divided into three tiers: ### Supported platforms -The community does not build or test against end of life distributions (EoL). -Thus we do not recommend that you use Node on end of life or unsupported platforms +The community does not build or test against end-of-life distributions (EoL). +Thus we do not recommend that you use Node on end-of-life or unsupported platforms in production. | System | Support type | Version | Architectures | Notes | |--------------|--------------|----------------------------------|----------------------|------------------| | GNU/Linux | Tier 1 | kernel >= 2.6.32, glibc >= 2.12 | x64, arm, arm64 | | | macOS | Tier 1 | >= 10.10 | x64 | | -| Windows | Tier 1 | >= Windows 7 / 2008 R2 | x86, x64 | vs2017 | +| Windows | Tier 1 | >= Windows 7/2008 R2 | x86, x64 | vs2017 | | SmartOS | Tier 2 | >= 15 < 16.4 | x86, x64 | see note1 | | FreeBSD | Tier 2 | >= 10 | x64 | | | GNU/Linux | Tier 2 | kernel >= 3.13.0, glibc >= 2.19 | ppc64le >=power8 | | @@ -92,7 +92,7 @@ Depending on host platform, the selection of toolchains may vary. *Note:* All prerequisites can be easily installed by following [this bootstrapping guide](https://github.com/nodejs/node/blob/master/tools/bootstrap/README.md). -### Unix / macOS +### Unix/macOS Prerequisites: @@ -101,7 +101,7 @@ Prerequisites: * Python 2.6 or 2.7 * GNU Make 3.81 or newer -On macOS you will need to install the `Xcode Command Line Tools` by running +On macOS, you will need to install the `Xcode Command Line Tools` by running `xcode-select --install`. Alternatively, if you already have the full Xcode installed, you can find them under the menu `Xcode -> Open Developer Tool -> More Developer Tools...`. This step will install `clang`, `clang++`, and @@ -114,7 +114,7 @@ If the path to your build directory contains a space, the build will likely fail ```console $ sudo ./tools/macosx-firewall.sh ``` -Running this script will add rules for the executable `node` in the out +Running this script will add rules for the executable `node` in the `out` directory and the symbolic `node` link in the project's root directory. On FreeBSD and OpenBSD, you may also need: @@ -233,7 +233,7 @@ To test if Node.js was built correctly: > Release\node -e "console.log('Hello from Node.js', process.version)" ``` -### Android / Android-based devices (e.g. Firefox OS) +### Android/Android-based devices (e.g. Firefox OS) Although these instructions for building on Android are provided, please note that Android is not an officially supported platform at this time. Patches to @@ -273,7 +273,7 @@ With the `--download=all`, this may download ICU if you don't have an ICU in `deps/icu`. (The embedded `small-icu` included in the default Node.js source does not include all locales.) -##### Unix / macOS: +##### Unix/macOS: ```console $ ./configure --with-intl=full-icu --download=all @@ -290,7 +290,7 @@ $ ./configure --with-intl=full-icu --download=all The `Intl` object will not be available, nor some other APIs such as `String.normalize`. -##### Unix / macOS: +##### Unix/macOS: ```console $ ./configure --without-intl @@ -302,7 +302,7 @@ $ ./configure --without-intl > .\vcbuild without-intl ``` -#### Use existing installed ICU (Unix / macOS only): +#### Use existing installed ICU (Unix/macOS only): ```console $ pkg-config --modversion icu-i18n && ./configure --with-intl=system-icu @@ -318,7 +318,7 @@ You can find other ICU releases at Download the file named something like `icu4c-**##.#**-src.tgz` (or `.zip`). -##### Unix / macOS +##### Unix/macOS From an already-unpacked ICU: ```console @@ -366,7 +366,7 @@ and [user guide](https://openssl.org/docs/fips/UserGuide-2.0.pdf). through which you get the file complies with the requirements for a "secure installation" as described in section 6.6 in the [user guide](https://openssl.org/docs/fips/UserGuide-2.0.pdf). - For evaluation/experimentation you can simply download and verify + For evaluation/experimentation, you can simply download and verify `openssl-fips-x.x.x.tar.gz` from https://www.openssl.org/source/ 2. Extract source to `openssl-fips` folder and `cd openssl-fips` 3. `./config` diff --git a/CHANGELOG.md b/CHANGELOG.md index 037787d6958..6b9fe7ac42e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,8 @@ release. </tr> <tr> <td valign="top"> -<b><a href="doc/changelogs/CHANGELOG_V9.md#9.3.0">9.3.0</a></b><br/> +<b><a href="doc/changelogs/CHANGELOG_V9.md#9.4.0">9.4.0</a></b><br/> +<a href="doc/changelogs/CHANGELOG_V9.md#9.3.0">9.3.0</a><br/> <a href="doc/changelogs/CHANGELOG_V9.md#9.2.1">9.2.1</a><br/> <a href="doc/changelogs/CHANGELOG_V9.md#9.2.0">9.2.0</a><br/> <a href="doc/changelogs/CHANGELOG_V9.md#9.1.0">9.1.0</a><br/> diff --git a/COLLABORATOR_GUIDE.md b/COLLABORATOR_GUIDE.md index 2569570b8d0..f96c9a2a0dd 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/benchmark/net/net-wrap-js-stream-passthrough.js b/benchmark/net/net-wrap-js-stream-passthrough.js new file mode 100644 index 00000000000..bf84285e81b --- /dev/null +++ b/benchmark/net/net-wrap-js-stream-passthrough.js @@ -0,0 +1,107 @@ +// test the speed of .pipe() with JSStream wrapping for PassThrough streams +'use strict'; + +const common = require('../common.js'); +const { PassThrough } = require('stream'); + +const bench = common.createBenchmark(main, { + len: [102400, 1024 * 1024 * 16], + type: ['utf', 'asc', 'buf'], + dur: [5], +}, { + flags: ['--expose-internals'] +}); + +var dur; +var len; +var type; +var chunk; +var encoding; +var JSStreamWrap; // Can only require internals inside main(). + +function main(conf) { + dur = +conf.dur; + len = +conf.len; + type = conf.type; + JSStreamWrap = require('internal/wrap_js_stream'); + + switch (type) { + case 'buf': + chunk = Buffer.alloc(len, 'x'); + break; + case 'utf': + encoding = 'utf8'; + chunk = 'ü'.repeat(len / 2); + break; + case 'asc': + encoding = 'ascii'; + chunk = 'x'.repeat(len); + break; + default: + throw new Error(`invalid type: ${type}`); + } + + doBenchmark(); +} + +function Writer() { + this.received = 0; + this.writable = true; +} + +Writer.prototype.write = function(chunk, encoding, cb) { + this.received += chunk.length; + + if (typeof encoding === 'function') + encoding(); + else if (typeof cb === 'function') + cb(); + + return true; +}; + +// doesn't matter, never emits anything. +Writer.prototype.on = function() {}; +Writer.prototype.once = function() {}; +Writer.prototype.emit = function() {}; +Writer.prototype.prependListener = function() {}; + + +function flow() { + const dest = this.dest; + const res = dest.write(chunk, encoding); + if (!res) + dest.once('drain', this.flow); + else + process.nextTick(this.flow); +} + +function Reader() { + this.flow = flow.bind(this); + this.readable = true; +} + +Reader.prototype.pipe = function(dest) { + this.dest = dest; + this.flow(); + return dest; +}; + + +function doBenchmark() { + const reader = new Reader(); + const writer = new Writer(); + + // the actual benchmark. + const fakeSocket = new JSStreamWrap(new PassThrough()); + bench.start(); + reader.pipe(fakeSocket); + fakeSocket.pipe(writer); + + setTimeout(function() { + const bytes = writer.received; + const gbits = (bytes * 8) / (1024 * 1024 * 1024); + bench.end(gbits); + process.exit(0); + }, dur * 1000); +} diff --git a/doc/api/child_process.md b/doc/api/child_process.md index 2f86d5156fc..c88443e078b 100644 --- a/doc/api/child_process.md +++ b/doc/api/child_process.md @@ -25,7 +25,7 @@ ls.on('close', (code) => { }); ``` -By default, pipes for `stdin`, `stdout` and `stderr` are established between +By default, pipes for `stdin`, `stdout`, and `stderr` are established between the parent Node.js process and the spawned child. It is possible to stream data through these pipes in a non-blocking way. *Note, however, that some programs use line-buffered I/O internally. While that does not affect Node.js, it can @@ -170,7 +170,7 @@ exec('echo "The \\$HOME variable is $HOME"'); //The $HOME variable is escaped in the first instance, but not in the second ``` -*Note*: Never pass unsanitised user input to this function. Any input +*Note*: Never pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution. @@ -418,7 +418,7 @@ The `child_process.spawn()` method spawns a new process using the given `command`, with command line arguments in `args`. If omitted, `args` defaults to an empty array. -*Note*: If the `shell` option is enabled, do not pass unsanitised user input to +*Note*: If the `shell` option is enabled, do not pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution. @@ -661,7 +661,7 @@ The [`child_process.spawnSync()`][], [`child_process.execSync()`][], and the Node.js event loop, pausing execution of any additional code until the spawned process exits. -Blocking calls like these are mostly useful for simplifying general purpose +Blocking calls like these are mostly useful for simplifying general-purpose scripting tasks and for simplifying the loading/processing of application configuration at startup. @@ -715,7 +715,7 @@ completely exited. does not exit, the parent process will still wait until the child process has exited. -If the process times out, or has a non-zero exit code, this method ***will*** +If the process times out or has a non-zero exit code, this method ***will*** throw an [`Error`][] that will include the full result of the underlying [`child_process.spawnSync()`][]. @@ -767,11 +767,11 @@ exited. *Note that if the child process intercepts and handles the `SIGTERM` signal and doesn't exit, the parent process will wait until the child process has exited.* -If the process times out, or has a non-zero exit code, this method ***will*** +If the process times out or has a non-zero exit code, this method ***will*** throw. The [`Error`][] object will contain the entire result from [`child_process.spawnSync()`][] -*Note*: Never pass unsanitised user input to this function. Any input +*Note*: Never pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution. @@ -839,7 +839,7 @@ completely exited. Note that if the process intercepts and handles the `SIGTERM` signal and doesn't exit, the parent process will wait until the child process has exited. -*Note*: If the `shell` option is enabled, do not pass unsanitised user input +*Note*: If the `shell` option is enabled, do not pass unsanitized user input to this function. Any input containing shell metacharacters may be used to trigger arbitrary command execution. diff --git a/doc/api/errors.md b/doc/api/errors.md index d199e3affd7..3f2737f4df6 100644 --- a/doc/api/errors.md +++ b/doc/api/errors.md @@ -1322,6 +1322,12 @@ While using `N-API`, a constructor passed was not a function. While using `N-API`, `Constructor.prototype` was not an object. +<a id="ERR_NAPI_INVALID_DATAVIEW_ARGS"></a> +### ERR_NAPI_INVALID_DATAVIEW_ARGS + +While calling `napi_create_dataview()`, a given `offset` was outside the bounds +of the dataview or `offset + length` was larger than a length of given `buffer`. + <a id="ERR_NO_CRYPTO"></a> ### ERR_NO_CRYPTO diff --git a/doc/api/events.md b/doc/api/events.md index d0bf2c1897a..7b510fac050 100644 --- a/doc/api/events.md +++ b/doc/api/events.md @@ -576,7 +576,7 @@ Returns a reference to the `EventEmitter`, so that calls can be chained. ### emitter.rawListeners(eventName) <!-- YAML -added: REPLACEME +added: v9.4.0 --> - `eventName` {string|symbol} diff --git a/doc/api/fs.md b/doc/api/fs.md index 47491cf5a74..e1dabde956c 100644 --- a/doc/api/fs.md +++ b/doc/api/fs.md @@ -2351,7 +2351,7 @@ changes: --> * `fd` {integer} -* `buffer` {string|Buffer|Uint8Array} +* `buffer` {Buffer|Uint8Array} * `offset` {integer} * `length` {integer} * `position` {integer} diff --git a/doc/api/http.md b/doc/api/http.md index a4ed90269d6..536d247226f 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -734,7 +734,7 @@ changes: description: The default action of calling `.destroy()` on the `socket` will no longer take place if there are listeners attached for `clientError`. - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/17672 description: The rawPacket is the current buffer that just parsed. Adding this buffer to the error object of clientError event is to make diff --git a/doc/api/http2.md b/doc/api/http2.md index 19455a55e07..09bce9d144d 100644 --- a/doc/api/http2.md +++ b/doc/api/http2.md @@ -285,7 +285,7 @@ session.on('timeout', () => { /** .. **/ }); #### http2session.alpnProtocol <!-- YAML -added: REPLACEME +added: v9.4.0 --> * Value: {string|undefined} @@ -297,7 +297,7 @@ property. #### http2session.close([callback]) <!-- YAML -added: REPLACEME +added: v9.4.0 --> * `callback` {Function} @@ -312,7 +312,7 @@ If specified, the `callback` function is registered as a handler for the #### http2session.closed <!-- YAML -added: REPLACEME +added: v9.4.0 --> * Value: {boolean} @@ -354,7 +354,7 @@ longer be used, otherwise `false`. #### http2session.encrypted <!-- YAML -added: REPLACEME +added: v9.4.0 --> * Value: {boolean|undefined} @@ -366,7 +366,7 @@ or stream. #### http2session.goaway([code, [lastStreamID, [opaqueData]]]) <!-- YAML -added: REPLACEME +added: v9.4.0 --> * `code` {number} An HTTP/2 error code @@ -389,7 +389,7 @@ A prototype-less object describing the current local settings of this #### http2session.originSet <!-- YAML -added: REPLACEME +added: v9.4.0 --> * Value: {string[]|undefined} @@ -450,7 +450,7 @@ If the `payload` argument is not specified, the default payload will be the #### http2session.ref() <!-- YAML -added: REPLACEME +added: v9.4.0 --> Calls [`ref()`][`net.Socket.prototype.ref`] on this `Http2Session` @@ -540,16 +540,28 @@ All other interactions will be routed directly to the socket. added: v8.4.0 --> +Provides miscellaneous information about the current state of the +`Http2Session`. + * Value: {Object} - * `effectiveLocalWindowSize` {number} - * `effectiveRecvDataLength` {number} - * `nextStreamID` {number} - * `localWindowSize` {number} - * `lastProcStreamID` {number} - * `remoteWindowSize` {number} - * `outboundQueueSize` {number} - * `deflateDynamicTableSize` {number} - * `inflateDynamicTableSize` {number} + * `effectiveLocalWindowSize` {number} The current local (receive) + flow control window size for the `Http2Session`. + * `effectiveRecvDataLength` {number} The current number of bytes + that have been received since the last flow control `WINDOW_UPDATE`. + * `nextStreamID` {number} The numeric identifier to be used the + next time a new `Http2Stream` is created by this `Http2Session`. + * `localWindowSize` {number} The number of bytes that the remote peer can + send without receiving a `WINDOW_UPDATE`. + * `lastProcStreamID` {number} The numeric id of the `Http2Stream` + for which a `HEADERS` or `DATA` frame was most recently received. + * `remoteWindowSize` {number} The number of bytes that this `Http2Session` + may send without receiving a `WINDOW_UPDATE`. + * `outboundQueueSize` {number} The number of frames currently within the + outbound queue for this `Http2Session`. + * `deflateDynamicTableSize` {number} The current size in bytes of the + outbound header compression state table. + * `inflateDynamicTableSize` {number} The current size in bytes of the + inbound header compression state table. An object describing the current status of this `Http2Session`. @@ -587,7 +599,7 @@ client. #### http2session.unref() <!-- YAML -added: REPLACEME +added: v9.4.0 --> Calls [`unref()`][`net.Socket.prototype.unref`] on this `Http2Session` @@ -600,7 +612,7 @@ added: v8.4.0 #### serverhttp2session.altsvc(alt, originOrStream) <!-- YAML -added: REPLACEME +added: v9.4.0 --> * `alt` {string} A description of the alternative service configuration as @@ -671,7 +683,7 @@ added: v8.4.0 #### Event: 'altsvc' <!-- YAML -added: REPLACEME +added: v9.4.0 --> The `'altsvc'` event is emitted whenever an `ALTSVC` frame is received by @@ -917,7 +929,7 @@ connected HTTP/2 peer. #### http2stream.closed <!-- YAML -added: REPLACEME +added: v9.4.0 --> * Value: {boolean} @@ -936,7 +948,7 @@ usable. #### http2stream.pending <!-- YAML -added: REPLACEME +added: v9.4.0 --> * Value: {boolean} @@ -1010,14 +1022,21 @@ req.setTimeout(5000, () => req.rstStream(NGHTTP2_CANCEL)); <!-- YAML added: v8.4.0 --> +Provides miscellaneous information about the current state of the +`Http2Stream`. * Value: {Object} - * `localWindowSize` {number} - * `state` {number} - * `localClose` {number} - * `remoteClose` {number} - * `sumDependencyWeight` {number} - * `weight` {number} + * `localWindowSize` {number} The number of bytes the connected peer may send + for this `Http2Stream` without receiving a `WINDOW_UPDATE`. + * `state` {number} A flag indicating the low-level current state of the + `Http2Stream` as determined by nghttp2. + * `localClose` {number} `true` if this `Http2Stream` has been closed locally. + * `remoteClose` {number} `true` if this `Http2Stream` has been closed + remotely. + * `sumDependencyWeight` {number} The sum weight of all `Http2Stream` + instances that depend on this `Http2Stream` as specified using + `PRIORITY` frames. + * `weight` {number} The priority weight of this `Http2Stream`. A current state of this `Http2Stream`. @@ -3003,23 +3022,35 @@ The `name` property of the `PerformanceEntry` will be equal to either If `name` is equal to `Http2Stream`, the `PerformanceEntry` will contain the following additional properties: +* `bytesRead` {number} The number of DATA frame bytes received for this + `Http2Stream`. +* `bytesWritten` {number} The number of DATA frame bytes sent for this + `Http2Stream`. +* `id` {number} The identifier of the associated `Http2Stream` * `timeToFirstByte` {number} The number of milliseconds elapsed between the `PerformanceEntry` `startTime` and the reception of the first `DATA` frame. +* `timeToFirstByteSent` {number} The number of milliseconds elapsed between + the `PerformanceEntry` `startTime` and sending of the first `DATA` frame. * `timeToFirstHeader` {number} The number of milliseconds elapsed between the `PerformanceEntry` `startTime` and the reception of the first header. If `name` is equal to `Http2Session`, the `PerformanceEntry` will contain the following additional properties: +* `bytesRead` {number} The number of bytes received for this `Http2Session`. +* `bytesWritten` {number} The number of bytes sent for this `Http2Session`. +* `framesReceived` {number} The number of HTTP/2 frames received by the + `Http2Session`. +* `framesSent` {number} The number of HTTP/2 frames sent by the `Http2Session`. +* `maxConcurrentStreams` {number} The maximum number of streams concurrently + open during the lifetime of the `Http2Session`. * `pingRTT` {number} The number of milliseconds elapsed since the transmission of a `PING` frame and the reception of its acknowledgment. Only present if a `PING` frame has been sent on the `Http2Session`. -* `streamCount` {number} The number of `Http2Stream` instances processed by - the `Http2Session`. * `streamAverageDuration` {number} The average duration (in milliseconds) for all `Http2Stream` instances. -* `framesReceived` {number} The number of HTTP/2 frames received by the - `Http2Session`. +* `streamCount` {number} The number of `Http2Stream` instances processed by + the `Http2Session`. * `type` {string} Either `'server'` or `'client'` to identify the type of `Http2Session`. diff --git a/doc/api/stream.md b/doc/api/stream.md index 10bd9515051..2166ae4eccc 100644 --- a/doc/api/stream.md +++ b/doc/api/stream.md @@ -446,7 +446,7 @@ Return the value of `highWaterMark` passed when constructing this ##### writable.writableLength <!-- YAML -added: REPLACEME +added: v9.4.0 --> This property contains the number of bytes (or objects) in the queue @@ -747,6 +747,12 @@ The listener callback will be passed a single `Error` object. ##### Event: 'readable' <!-- YAML added: v0.9.4 +changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/17979 + description: > + 'readable' is always emitted in the next tick after + .push() is called --> The `'readable'` event is emitted when there is data available to be read from @@ -955,7 +961,7 @@ event has been emitted will return `null`. No runtime error will be raised. ##### readable.readableLength <!-- YAML -added: REPLACEME +added: v9.4.0 --> This property contains the number of bytes (or objects) in the queue @@ -1647,6 +1653,13 @@ const myReadable = new Readable({ ``` #### readable.\_read(size) +<!-- YAML +added: v0.9.4 +changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/17979 + description: call _read() only once per microtick +--> * `size` {number} Number of bytes to read asynchronously @@ -1666,6 +1679,8 @@ additional data onto the queue. *Note*: Once the `readable._read()` method has been called, it will not be called again until the [`readable.push()`][stream-push] method is called. +`readable._read()` is guaranteed to be called only once within a +synchronous execution, i.e. a microtick. The `size` argument is advisory. For implementations where a "read" is a single operation that returns data can use the `size` argument to determine how diff --git a/doc/api/zlib.md b/doc/api/zlib.md index 7a827070206..909a52d6e54 100644 --- a/doc/api/zlib.md +++ b/doc/api/zlib.md @@ -286,7 +286,7 @@ Compression strategy. <!-- YAML added: v0.11.1 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `dictionary` option can be an ArrayBuffer. - version: v8.0.0 @@ -526,7 +526,7 @@ without a callback. <!-- YAML added: v0.6.0 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 @@ -540,7 +540,7 @@ changes: <!-- YAML added: v0.11.12 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 @@ -570,7 +570,7 @@ changes: <!-- YAML added: v0.11.12 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 @@ -589,7 +589,7 @@ Compress a chunk of data with [DeflateRaw][]. <!-- YAML added: v0.6.0 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 @@ -603,7 +603,7 @@ changes: <!-- YAML added: v0.11.12 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 @@ -622,7 +622,7 @@ Decompress a chunk of data with [Gunzip][]. <!-- YAML added: v0.6.0 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 @@ -636,7 +636,7 @@ changes: <!-- YAML added: v0.11.12 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 @@ -655,7 +655,7 @@ Compress a chunk of data with [Gzip][]. <!-- YAML added: v0.6.0 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 @@ -669,7 +669,7 @@ changes: <!-- YAML added: v0.11.12 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 @@ -688,7 +688,7 @@ Decompress a chunk of data with [Inflate][]. <!-- YAML added: v0.6.0 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 @@ -702,7 +702,7 @@ changes: <!-- YAML added: v0.11.12 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 @@ -721,7 +721,7 @@ Decompress a chunk of data with [InflateRaw][]. <!-- YAML added: v0.6.0 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 @@ -735,7 +735,7 @@ changes: <!-- YAML added: v0.11.12 changes: - - version: REPLACEME + - version: v9.4.0 pr-url: https://github.com/nodejs/node/pull/16042 description: The `buffer` parameter can be an ArrayBuffer. - version: v8.0.0 diff --git a/doc/changelogs/CHANGELOG_V9.md b/doc/changelogs/CHANGELOG_V9.md index 9660e68b429..57fb7825f02 100644 --- a/doc/changelogs/CHANGELOG_V9.md +++ b/doc/changelogs/CHANGELOG_V9.md @@ -8,6 +8,7 @@ </tr> <tr> <td> +<a href="#9.4.0">9.4.0</a><br/> <a href="#9.3.0">9.3.0</a><br/> <a href="#9.2.1">9.2.1</a><br/> <a href="#9.2.0">9.2.0</a><br/> @@ -28,6 +29,281 @@ * [io.js](CHANGELOG_IOJS.md) * [Archive](CHANGELOG_ARCHIVE.md) +<a id="9.4.0"></a> +## 2018-01-10, Version 9.4.0 (Current), @MylesBorins + +### Notable Changes + +* **async\_hooks**: + - deprecate AsyncHooks Sensitive API and runInAsyncIdScope. Neither API were documented. (Andreas Madsen) [#16972](https://github.com/nodejs/node/pull/16972) +* **deps**: + - update nghttp2 to 1.29.0 (James M Snell) [#17908](https://github.com/nodejs/node/pull/17908) + - upgrade npm to 5.6.0 (Kat Marchán) [#17535](https://github.com/nodejs/node/pull/17535) + - cherry-pick 50f7455 from upstream V8 (Michaël Zasso) [#16591](https://github.com/nodejs/node/pull/16591) +* **events**: + - remove reaches into _events internals (Anatoli Papirovski) [#17440](https://github.com/nodejs/node/pull/17440) +* **http**: + - add rawPacket in err of `clientError` event (XadillaX) [#17672](https://github.com/nodejs/node/pull/17672) +* **http2**: + - implement maxSessionMemory (James M Snell) [#17967](https://github.com/nodejs/node/pull/17967) + - add initial support for originSet (James M Snell) [#17935](https://github.com/nodejs/node/pull/17935) + - add altsvc support (James M Snell) [#17917](https://github.com/nodejs/node/pull/17917) + - perf_hooks integration (James M Snell) [#17906](https://github.com/nodejs/node/pull/17906) + - Refactoring and cleanup of Http2Session and Http2Stream destroy (James M Snell) [#17406](https://github.com/nodejs/node/pull/17406) +* **net**: + - remove Socket.prototype.listen (Ruben Bridgewater) [#13735](https://github.com/nodejs/node/pull/13735) +* **repl**: + - show lexically scoped vars in tab completion (Michaël Zasso) [#16591](https://github.com/nodejs/node/pull/16591) +* **stream**: + - rm {writeable/readable}State.length (Calvin Metcalf) [#12857](https://github.com/nodejs/node/pull/12857) + - add flow and buffer properties to streams (Calvin Metcalf) [#12855](https://github.com/nodejs/node/pull/12855) +* **util**: + - allow wildcards in NODE_DEBUG variable (Tyler) [#17609](https://github.com/nodejs/node/pull/17609) +* **zlib**: + - add ArrayBuffer support (Jem Bezooyen) [#16042](https://github.com/nodejs/node/pull/16042) +* **Added new collaborator** + - [starkwang](https://github.com/starkwang) Weijia Wang +* **Added new TSC member** + - [danbev](https://github.com/danbev) Daniel Bevenius + +### Commits + +* [[`ec443c3430`](https://github.com/nodejs/node/commit/ec443c3430)] - **assert**: fix .throws operator (Ruben Bridgewater) [#17575](https://github.com/nodejs/node/pull/17575) +* [[`0843ed6ae7`](https://github.com/nodejs/node/commit/0843ed6ae7)] - **async_hooks**: use CHECK instead of throwing error (Jon Moss) [#17832](https://github.com/nodejs/node/pull/17832) +* [[`23f4433f89`](https://github.com/nodejs/node/commit/23f4433f89)] - **(SEMVER-MINOR)** **async_hooks**: deprecate undocumented API (Andreas Madsen) [#16972](https://github.com/nodejs/node/pull/16972) +* [[`63c23a1ff2`](https://github.com/nodejs/node/commit/63c23a1ff2)] - **benchmark**: fix timeout in write-stream-throughput (Anatoli Papirovski) [#17958](https://github.com/nodejs/node/pull/17958) +* [[`14eb97ebf7`](https://github.com/nodejs/node/commit/14eb97ebf7)] - **benchmark**: make temp file path configurable (Rich Trott) [#17811](https://github.com/nodejs/node/pull/17811) +* [[`27227cf4c7`](https://github.com/nodejs/node/commit/27227cf4c7)] - **benchmark**: refactor console benchmark (Ruben Bridgewater) [#17707](https://github.com/nodejs/node/pull/17707) +* [[`0aa403b649`](https://github.com/nodejs/node/commit/0aa403b649)] - **buffer**: optimize readDouble and readFloat methods (Ben Noordhuis) [#17775](https://github.com/nodejs/node/pull/17775) +* [[`d93b4765a5`](https://github.com/nodejs/node/commit/d93b4765a5)] - **build**: document targets in the Makefile (Joyee Cheung) [#16975](https://github.com/nodejs/node/pull/16975) +* [[`224033db56`](https://github.com/nodejs/node/commit/224033db56)] - **build**: put .PHONY directly before its target (Oky Antoro) [#17964](https://github.com/nodejs/node/pull/17964) +* [[`2d857ed7c8`](https://github.com/nodejs/node/commit/2d857ed7c8)] - **build**: remove duplicate async-hooks and known_issues test runs (Rich Trott) [#17912](https://github.com/nodejs/node/pull/17912) +* [[`d066db7014`](https://github.com/nodejs/node/commit/d066db7014)] - **cluster**: support windowsHide option for workers (Todd Wong) [#17412](https://github.com/nodejs/node/pull/17412) +* [[`28283efd89`](https://github.com/nodejs/node/commit/28283efd89)] - **console**: order functions and remove \n\n (Ruben Bridgewater) [#17707](https://github.com/nodejs/node/pull/17707) +* [[`41e2bb185d`](https://github.com/nodejs/node/commit/41e2bb185d)] - **console**: make variables and checks stricter (Ruben Bridgewater) [#17707](https://github.com/nodejs/node/pull/17707) +* [[`0573c0fb23`](https://github.com/nodejs/node/commit/0573c0fb23)] - **console**: make error handling engine agnostic (Ruben Bridgewater) [#17707](https://github.com/nodejs/node/pull/17707) +* [[`1b8d3ec5e7`](https://github.com/nodejs/node/commit/1b8d3ec5e7)] - **crypto**: add ocsp_request ClientHelloParser::Reset (Daniel Bevenius) [#17753](https://github.com/nodejs/node/pull/17753) +* [[`d387c178b2`](https://github.com/nodejs/node/commit/d387c178b2)] - **crypto**: warn on invalid authentication tag length (Tobias Nießen) [#17566](https://github.com/nodejs/node/pull/17566) +* [[`7153434fae`](https://github.com/nodejs/node/commit/7153434fae)] - **crypto**: reuse variable instead of reevaluation (Tobias Nießen) [#17735](https://github.com/nodejs/node/pull/17735) +* [[`7d03567287`](https://github.com/nodejs/node/commit/7d03567287)] - **crypto**: remove unused header in clienthello.h (Daniel Bevenius) [#17752](https://github.com/nodejs/node/pull/17752) +* [[`dfb9b5e83a`](https://github.com/nodejs/node/commit/dfb9b5e83a)] - **crypto**: move node_crypto_clienthello-inl.h to cc (Daniel Bevenius) [#17606](https://github.com/nodejs/node/pull/17606) +* [[`43fbc393e3`](https://github.com/nodejs/node/commit/43fbc393e3)] - **deps**: cherry-pick 50f7455 from upstream V8 (Michaël Zasso) [#16591](https://github.com/nodejs/node/pull/16591) +* [[`5df8c76ea9`](https://github.com/nodejs/node/commit/5df8c76ea9)] - **deps**: update nghttp2 to 1.29.0 (James M Snell) [#17908](https://github.com/nodejs/node/pull/17908) +* [[`8f3b2d7e8a`](https://github.com/nodejs/node/commit/8f3b2d7e8a)] - **deps**: V8: cherry-pick ac0fe8ec from upstream (Ali Ijaz Sheikh) [#17695](https://github.com/nodejs/node/pull/17695) +* [[`ffe1ad6c12`](https://github.com/nodejs/node/commit/ffe1ad6c12)] - **deps**: upgrade npm to 5.6.0 (Kat Marchán) [#17535](https://github.com/nodejs/node/pull/17535) +* [[`ffc2659964`](https://github.com/nodejs/node/commit/ffc2659964)] - **doc**: fix incorrect argument type in fs.readSync (Mykola Bilochub) [#18022](https://github.com/nodejs/node/pull/18022) +* [[`ef317014e2`](https://github.com/nodejs/node/commit/ef317014e2)] - **doc**: compact eslint directives in common/README (Vse Mozhet Byt) [#17971](https://github.com/nodejs/node/pull/17971) +* [[`3623cf7ec7`](https://github.com/nodejs/node/commit/3623cf7ec7)] - **doc**: add guide on maintaining build files (Joyee Cheung) [#16975](https://github.com/nodejs/node/pull/16975) +* [[`b593d946e4`](https://github.com/nodejs/node/commit/b593d946e4)] - **doc**: re-alphabetise sections in common/README.md (Vse Mozhet Byt) [#17971](https://github.com/nodejs/node/pull/17971) +* [[`3bcdb3b996`](https://github.com/nodejs/node/commit/3bcdb3b996)] - **doc**: fix code nits in common/README (Vse Mozhet Byt) [#17971](https://github.com/nodejs/node/pull/17971) +* [[`0ad783afaf`](https://github.com/nodejs/node/commit/0ad783afaf)] - **doc**: fix link for https api change (Myles Borins) [#17630](https://github.com/nodejs/node/pull/17630) +* [[`1181ff7ecc`](https://github.com/nodejs/node/commit/1181ff7ecc)] - **doc**: correct spelling (sreepurnajasti) [#17911](https://github.com/nodejs/node/pull/17911) +* [[`43ac36c6de`](https://github.com/nodejs/node/commit/43ac36c6de)] - **doc**: grammar fixes in http2.md (Rich Trott) [#17972](https://github.com/nodejs/node/pull/17972) +* [[`46f39b590b`](https://github.com/nodejs/node/commit/46f39b590b)] - **doc**: add docs for common/http2.js utility (James M Snell) [#17942](https://github.com/nodejs/node/pull/17942) +* [[`83c725dc73`](https://github.com/nodejs/node/commit/83c725dc73)] - **doc**: updates examples to use NULL (Michael Dawson) [#18008](https://github.com/nodejs/node/pull/18008) +* [[`72ed11ac78`](https://github.com/nodejs/node/commit/72ed11ac78)] - **doc**: move matthewloring to emeriti (Rich Trott) [#17998](https://github.com/nodejs/node/pull/17998) +* [[`6efef47c2a`](https://github.com/nodejs/node/commit/6efef47c2a)] - **doc**: move joshgav to TSC emeriti list (Rich Trott) [#17953](https://github.com/nodejs/node/pull/17953) +* [[`294c5f4ef0`](https://github.com/nodejs/node/commit/294c5f4ef0)] - **doc**: improve security section of README.md (Rich Trott) [#17929](https://github.com/nodejs/node/pull/17929) +* [[`445c911ba4`](https://github.com/nodejs/node/commit/445c911ba4)] - **doc**: edit for concision (Rich Trott) [#17891](https://github.com/nodejs/node/pull/17891) +* [[`3fd65815f8`](https://github.com/nodejs/node/commit/3fd65815f8)] - **doc**: remove x86 from os.arch() options (Gibson Fahnestock) [#17899](https://github.com/nodejs/node/pull/17899) +* [[`14499f8185`](https://github.com/nodejs/node/commit/14499f8185)] - **doc**: improve PR-review paragraph in CONTRIBUTING.md (Rich Trott) [#17931](https://github.com/nodejs/node/pull/17931) +* [[`54cf75ddb5`](https://github.com/nodejs/node/commit/54cf75ddb5)] - **doc**: fix typos in CONTRIBUTING.md (Rich Trott) [#17930](https://github.com/nodejs/node/pull/17930) +* [[`16fbd5718a`](https://github.com/nodejs/node/commit/16fbd5718a)] - **doc**: remove non-style information from style guide (Rich Trott) [#17866](https://github.com/nodejs/node/pull/17866) +* [[`a702fcbd4b`](https://github.com/nodejs/node/commit/a702fcbd4b)] - **doc**: copy-edit COLLABORATOR_GUIDE.md (Rich Trott) [#17922](https://github.com/nodejs/node/pull/17922) +* [[`240121ec42`](https://github.com/nodejs/node/commit/240121ec42)] - **doc**: improve alt text (Rich Trott) [#17922](https://github.com/nodejs/node/pull/17922) +* [[`312ad06cfe`](https://github.com/nodejs/node/commit/312ad06cfe)] - **doc**: fix spelling of contributors (Rich Trott) [#17922](https://github.com/nodejs/node/pull/17922) +* [[`2f7030de31`](https://github.com/nodejs/node/commit/2f7030de31)] - **doc**: add references to PR communication articles (Salame William) [#17902](https://github.com/nodejs/node/pull/17902) +* [[`d2b1601bd3`](https://github.com/nodejs/node/commit/d2b1601bd3)] - **doc**: replace wrong U+00A0 by common spaces (Vse Mozhet Byt) [#17940](https://github.com/nodejs/node/pull/17940) +* [[`658bdb34aa`](https://github.com/nodejs/node/commit/658bdb34aa)] - **doc**: remove duplicate words in API docs (Tobias Nießen) [#17937](https://github.com/nodejs/node/pull/17937) +* [[`181b8970b1`](https://github.com/nodejs/node/commit/181b8970b1)] - **doc**: fix duplicate words & spellings in docs (sreepurnajasti) [#17923](https://github.com/nodejs/node/pull/17923) +* [[`4850c87348`](https://github.com/nodejs/node/commit/4850c87348)] - **doc**: doc imitating the old behavior of http.Server.keepAliveTimeout (Tyson Andre) [#17660](https://github.com/nodejs/node/pull/17660) +* [[`b15f029b04`](https://github.com/nodejs/node/commit/b15f029b04)] - **doc**: fs doc improvements (James M Snell) [#17831](https://github.com/nodejs/node/pull/17831) +* [[`9fc9bb1c09`](https://github.com/nodejs/node/commit/9fc9bb1c09)] - **doc**: fix typo (Tobias Nießen) [#17900](https://github.com/nodejs/node/pull/17900) +* [[`2c9dab313e`](https://github.com/nodejs/node/commit/2c9dab313e)] - **doc**: use my legal name in README (Timothy Gu) [#17894](https://github.com/nodejs/node/pull/17894) +* [[`cb127de634`](https://github.com/nodejs/node/commit/cb127de634)] - **doc**: improve module.builtinModules text (Rich Trott) [#17865](https://github.com/nodejs/node/pull/17865) +* [[`1be0086ec8`](https://github.com/nodejs/node/commit/1be0086ec8)] - **doc**: use dashes instead of asterisks (Ruben Bridgewater) [#17722](https://github.com/nodejs/node/pull/17722) +* [[`26fbb0f78a`](https://github.com/nodejs/node/commit/26fbb0f78a)] - **doc**: use consistent new lines (Ruben Bridgewater) [#17722](https://github.com/nodejs/node/pull/17722) +* [[`a63d3c514d`](https://github.com/nodejs/node/commit/a63d3c514d)] - **doc**: update formatting to fit our 80 chars rule (Ruben Bridgewater) [#17722](https://github.com/nodejs/node/pull/17722) +* [[`59711ae42a`](https://github.com/nodejs/node/commit/59711ae42a)] - **doc**: update AUTHORS list (Ruben Bridgewater) [#17805](https://github.com/nodejs/node/pull/17805) +* [[`2d11f6b669`](https://github.com/nodejs/node/commit/2d11f6b669)] - **doc**: add starkwang to collaborators (Weijia Wang) [#17847](https://github.com/nodejs/node/pull/17847) +* [[`fe1f67f184`](https://github.com/nodejs/node/commit/fe1f67f184)] - **doc**: mark DEP0002 as end of life (Jon Moss) [#17815](https://github.com/nodejs/node/pull/17815) +* [[`d4666d0d7a`](https://github.com/nodejs/node/commit/d4666d0d7a)] - **doc**: require CI status indicator in PRs (Nikolai Vavilov) [#17151](https://github.com/nodejs/node/pull/17151) +* [[`541d189db9`](https://github.com/nodejs/node/commit/541d189db9)] - **doc**: use american spelling as per style guide (sreepurnajasti) [#17818](https://github.com/nodejs/node/pull/17818) +* [[`69945596e4`](https://github.com/nodejs/node/commit/69945596e4)] - **doc**: removed extra explanation in api/buffer.md (Waleed Ashraf) [#17796](https://github.com/nodejs/node/pull/17796) +* [[`c328e580d1`](https://github.com/nodejs/node/commit/c328e580d1)] - **doc**: improve module.builtinModules documentation (Thomas Watson) [#17712](https://github.com/nodejs/node/pull/17712) +* [[`1d935a0b2d`](https://github.com/nodejs/node/commit/1d935a0b2d)] - **doc**: instructions on how to make membership public (Michael Dawson) [#17688](https://github.com/nodejs/node/pull/17688) +* [[`b6d2090c8b`](https://github.com/nodejs/node/commit/b6d2090c8b)] - **doc**: improve fs api descriptions (Evan Lucas) [#17679](https://github.com/nodejs/node/pull/17679) +* [[`b1a8ac7774`](https://github.com/nodejs/node/commit/b1a8ac7774)] - **doc**: remove old console note (Ruben Bridgewater) [#17707](https://github.com/nodejs/node/pull/17707) +* [[`c982494433`](https://github.com/nodejs/node/commit/c982494433)] - **doc**: remove duplicate the from onboarding.md (sreepurnajasti) [#17733](https://github.com/nodejs/node/pull/17733) +* [[`206c4f85c5`](https://github.com/nodejs/node/commit/206c4f85c5)] - **doc**: fix typo in README.md (Weijia Wang) [#17729](https://github.com/nodejs/node/pull/17729) +* [[`dbc554a225`](https://github.com/nodejs/node/commit/dbc554a225)] - **doc**: fix typo in child_process.md (Rich Trott) [#17727](https://github.com/nodejs/node/pull/17727) +* [[`dd9d07caa7`](https://github.com/nodejs/node/commit/dd9d07caa7)] - **doc**: remove unused link definition (Jon Moss) [#17741](https://github.com/nodejs/node/pull/17741) +* [[`dcfe840a1e`](https://github.com/nodejs/node/commit/dcfe840a1e)] - **doc**: edit CONTRIBUTING.md preamble (Rich Trott) [#17700](https://github.com/nodejs/node/pull/17700) +* [[`ed9f2fef70`](https://github.com/nodejs/node/commit/ed9f2fef70)] - **doc**: improve release guide (Evan Lucas) [#17677](https://github.com/nodejs/node/pull/17677) +* [[`861f6adb70`](https://github.com/nodejs/node/commit/861f6adb70)] - **doc**: some fs doc improvements (James M Snell) [#17692](https://github.com/nodejs/node/pull/17692) +* [[`ecbc70fe5d`](https://github.com/nodejs/node/commit/ecbc70fe5d)] - **doc**: not all example code can be run without 1:1 (Jeremiah Senkpiel) [#17702](https://github.com/nodejs/node/pull/17702) +* [[`68722fd16e`](https://github.com/nodejs/node/commit/68722fd16e)] - **doc**: adjust TTY wording & add inter-doc links (Jeremiah Senkpiel) [#17702](https://github.com/nodejs/node/pull/17702) +* [[`d19343147b`](https://github.com/nodejs/node/commit/d19343147b)] - **doc**: fix fs.existsSync description (Jeremiah Senkpiel) [#17702](https://github.com/nodejs/node/pull/17702) +* [[`444362e048`](https://github.com/nodejs/node/commit/444362e048)] - **doc**: improve documentation.md (Jeremiah Senkpiel) [#17702](https://github.com/nodejs/node/pull/17702) +* [[`d1af106b76`](https://github.com/nodejs/node/commit/d1af106b76)] - **doc**: add countdown module to writing tests guide (Bamieh) [#17201](https://github.com/nodejs/node/pull/17201) +* [[`e059bc5503`](https://github.com/nodejs/node/commit/e059bc5503)] - **doc**: change "Node.js style cb" to "error-first cb" (Ram Goli) [#17638](https://github.com/nodejs/node/pull/17638) +* [[`712848bc7d`](https://github.com/nodejs/node/commit/712848bc7d)] - **doc**: change eventName type annotations (April Webster) [#17666](https://github.com/nodejs/node/pull/17666) +* [[`c24b4dd898`](https://github.com/nodejs/node/commit/c24b4dd898)] - **doc**: remove extra whitespace in module docs (Thomas Watson) [#17711](https://github.com/nodejs/node/pull/17711) +* [[`af1b340e39`](https://github.com/nodejs/node/commit/af1b340e39)] - **doc**: add C++ style comments to the style guide (Matheus Marchini) [#17617](https://github.com/nodejs/node/pull/17617) +* [[`5999a11526`](https://github.com/nodejs/node/commit/5999a11526)] - **doc**: include Daniel Bevenius as a TSC member (Rich Trott) [#17652](https://github.com/nodejs/node/pull/17652) +* [[`977fb13bd5`](https://github.com/nodejs/node/commit/977fb13bd5)] - **doc**: import() is supported now (Gus Caplan) [#17395](https://github.com/nodejs/node/pull/17395) +* [[`ed4d013f48`](https://github.com/nodejs/node/commit/ed4d013f48)] - **doc**: correct pbkdf2 salt length recommendation (Will Clark) [#17524](https://github.com/nodejs/node/pull/17524) +* [[`d70e6dc850`](https://github.com/nodejs/node/commit/d70e6dc850)] - **doc**: note that randomBytes throws when passed null (Tobias Nießen) [#17594](https://github.com/nodejs/node/pull/17594) +* [[`da448216cc`](https://github.com/nodejs/node/commit/da448216cc)] - **doc**: clearify promisify behavior for bad arguments (Ram Goli) [#17593](https://github.com/nodejs/node/pull/17593) +* [[`26025dec62`](https://github.com/nodejs/node/commit/26025dec62)] - **doc**: replace ArrayBufferView in crypto (Tobias Nießen) [#17595](https://github.com/nodejs/node/pull/17595) +* [[`1a84005150`](https://github.com/nodejs/node/commit/1a84005150)] - **doc,test**: mention Duplex support for TLS (Anna Henningsen) [#17599](https://github.com/nodejs/node/pull/17599) +* [[`7008719fb6`](https://github.com/nodejs/node/commit/7008719fb6)] - **(SEMVER-MINOR)** **events**: remove reaches into _events internals (Anatoli Papirovski) [#17440](https://github.com/nodejs/node/pull/17440) +* [[`f1485565ef`](https://github.com/nodejs/node/commit/f1485565ef)] - **fs**: guarantee order of callbacks in ws.close (Matteo Collina) [#18002](https://github.com/nodejs/node/pull/18002) +* [[`66c1a038a1`](https://github.com/nodejs/node/commit/66c1a038a1)] - **gitignore**: ignore *.VC.db files (Tobias Nießen) [#17898](https://github.com/nodejs/node/pull/17898) +* [[`8e1011f93b`](https://github.com/nodejs/node/commit/8e1011f93b)] - **http**: remove duplicate export (Evan Lucas) [#17982](https://github.com/nodejs/node/pull/17982) +* [[`f82439b6a0`](https://github.com/nodejs/node/commit/f82439b6a0)] - **(SEMVER-MINOR)** **http**: add rawPacket in err of `clientError` event (XadillaX) [#17672](https://github.com/nodejs/node/pull/17672) +* [[`9306de280f`](https://github.com/nodejs/node/commit/9306de280f)] - **http**: remove adapter frame from onParserExecute (Ben Noordhuis) [#17693](https://github.com/nodejs/node/pull/17693) +* [[`1ad7df6acc`](https://github.com/nodejs/node/commit/1ad7df6acc)] - **http2**: use aliased buffer for perf stats, add stats (James M Snell) [#18020](https://github.com/nodejs/node/pull/18020) +* [[`6a67dfd927`](https://github.com/nodejs/node/commit/6a67dfd927)] - **http2**: verify flood error and unsolicited frames (James M Snell) [#17969](https://github.com/nodejs/node/pull/17969) +* [[`6839283403`](https://github.com/nodejs/node/commit/6839283403)] - **http2**: verify that a dependency cycle may exist (James M Snell) [#17968](https://github.com/nodejs/node/pull/17968) +* [[`865da60e75`](https://github.com/nodejs/node/commit/865da60e75)] - **http2**: implement maxSessionMemory (James M Snell) [#17967](https://github.com/nodejs/node/pull/17967) +* [[`f17a5b92dc`](https://github.com/nodejs/node/commit/f17a5b92dc)] - **http2**: properly handle already closed stream error (James M Snell) [#17942](https://github.com/nodejs/node/pull/17942) +* [[`79d3198b7f`](https://github.com/nodejs/node/commit/79d3198b7f)] - **http2**: add aligned padding strategy (James M Snell) [#17938](https://github.com/nodejs/node/pull/17938) +* [[`2b6a5d90bd`](https://github.com/nodejs/node/commit/2b6a5d90bd)] - **http2**: add initial support for originSet (James M Snell) [#17935](https://github.com/nodejs/node/pull/17935) +* [[`9ad7a9a333`](https://github.com/nodejs/node/commit/9ad7a9a333)] - **http2**: add altsvc support (James M Snell) [#17917](https://github.com/nodejs/node/pull/17917) +* [[`e7a727e9ba`](https://github.com/nodejs/node/commit/e7a727e9ba)] - **http2**: strictly limit number on concurrent streams (James M Snell) [#16766](https://github.com/nodejs/node/pull/16766) +* [[`06aaaa8ad7`](https://github.com/nodejs/node/commit/06aaaa8ad7)] - **http2**: perf_hooks integration (James M Snell) [#17906](https://github.com/nodejs/node/pull/17906) +* [[`a003ded7fb`](https://github.com/nodejs/node/commit/a003ded7fb)] - **http2**: remove duplicate words in comments (Tobias Nießen) [#17939](https://github.com/nodejs/node/pull/17939) +* [[`1b7ce1ea02`](https://github.com/nodejs/node/commit/1b7ce1ea02)] - **http2**: implement ref() and unref() on client sessions (Kelvin Jin) [#17620](https://github.com/nodejs/node/pull/17620) +* [[`b8deb7522f`](https://github.com/nodejs/node/commit/b8deb7522f)] - **http2**: keep session objects alive during Http2Scope (Anna Henningsen) [#17863](https://github.com/nodejs/node/pull/17863) +* [[`e3c567f05b`](https://github.com/nodejs/node/commit/e3c567f05b)] - **http2**: fix compiling with `--debug-http2` (Anna Henningsen) [#17863](https://github.com/nodejs/node/pull/17863) +* [[`3a6b2ad19a`](https://github.com/nodejs/node/commit/3a6b2ad19a)] - **http2**: convert Http2Settings to an AsyncWrap (James M Snell) [#17763](https://github.com/nodejs/node/pull/17763) +* [[`bfc7e014cc`](https://github.com/nodejs/node/commit/bfc7e014cc)] - **http2**: refactor outgoing write mechanism (Anna Henningsen) [#17718](https://github.com/nodejs/node/pull/17718) +* [[`9592691d56`](https://github.com/nodejs/node/commit/9592691d56)] - **http2**: remove redundant write indirection (Anna Henningsen) [#17718](https://github.com/nodejs/node/pull/17718) +* [[`5abb60933e`](https://github.com/nodejs/node/commit/5abb60933e)] - **http2**: cleanup Http2Stream/Http2Session destroy (James M Snell) [#17406](https://github.com/nodejs/node/pull/17406) +* [[`f699a74e66`](https://github.com/nodejs/node/commit/f699a74e66)] - **http2**: be sure to destroy the Http2Stream (James M Snell) [#17406](https://github.com/nodejs/node/pull/17406) +* [[`30e75e601b`](https://github.com/nodejs/node/commit/30e75e601b)] - **http2**: only schedule write when necessary (Anna Henningsen) [#17183](https://github.com/nodejs/node/pull/17183) +* [[`d06ad0d4f0`](https://github.com/nodejs/node/commit/d06ad0d4f0)] - **http2**: don't call into JS from GC (Anna Henningsen) [#17183](https://github.com/nodejs/node/pull/17183) +* [[`f18d826660`](https://github.com/nodejs/node/commit/f18d826660)] - **http2**: simplify onSelectPadding (Anna Henningsen) [#17717](https://github.com/nodejs/node/pull/17717) +* [[`8d4fca3fb5`](https://github.com/nodejs/node/commit/8d4fca3fb5)] - **inspector**: make Coverity happy (Eugene Ostroukhov) [#17656](https://github.com/nodejs/node/pull/17656) +* [[`b817a8a6b2`](https://github.com/nodejs/node/commit/b817a8a6b2)] - **lib**: enable dot-notation eslint rule (Anatoli Papirovski) [#18007](https://github.com/nodejs/node/pull/18007) +* [[`2d61b9eb9f`](https://github.com/nodejs/node/commit/2d61b9eb9f)] - **lib, src**: use process.config instead of regex (Jon Moss) [#17814](https://github.com/nodejs/node/pull/17814) +* [[`3b2d8cba23`](https://github.com/nodejs/node/commit/3b2d8cba23)] - **module**: print better message on esm import error (Michaël Zasso) [#17786](https://github.com/nodejs/node/pull/17786) +* [[`79a283307a`](https://github.com/nodejs/node/commit/79a283307a)] - **n-api**: fix memory leak in napi_async_destroy() (alnyan) [#17714](https://github.com/nodejs/node/pull/17714) +* [[`74a5bbaff4`](https://github.com/nodejs/node/commit/74a5bbaff4)] - **net**: remove ADDRCONFIG DNS hint on Windows (Bartosz Sosnowski) [#17662](https://github.com/nodejs/node/pull/17662) +* [[`c3810e27bd`](https://github.com/nodejs/node/commit/c3810e27bd)] - **net**: remove Socket.prototype.write (Anna Henningsen) [#17644](https://github.com/nodejs/node/pull/17644) +* [[`e58a5ca854`](https://github.com/nodejs/node/commit/e58a5ca854)] - **net**: remove Socket.prototype.listen (Ruben Bridgewater) [#13735](https://github.com/nodejs/node/pull/13735) +* [[`0e116a01c8`](https://github.com/nodejs/node/commit/0e116a01c8)] - **perf_hooks**: fix scheduling regression (Anatoli Papirovski) [#18051](https://github.com/nodejs/node/pull/18051) +* [[`a329cf62ab`](https://github.com/nodejs/node/commit/a329cf62ab)] - **perf_hooks**: refactor internals (James M Snell) [#17822](https://github.com/nodejs/node/pull/17822) +* [[`bf0a7b6e13`](https://github.com/nodejs/node/commit/bf0a7b6e13)] - **process**: fix coverage generation (Evan Lucas) [#17651](https://github.com/nodejs/node/pull/17651) +* [[`b1bc768a57`](https://github.com/nodejs/node/commit/b1bc768a57)] - **readline**: refactor filter() callback (Rich Trott) [#17858](https://github.com/nodejs/node/pull/17858) +* [[`3831d87514`](https://github.com/nodejs/node/commit/3831d87514)] - **repl**: show lexically scoped vars in tab completion (Michaël Zasso) [#16591](https://github.com/nodejs/node/pull/16591) +* [[`2cc50530d2`](https://github.com/nodejs/node/commit/2cc50530d2)] - **repl**: fix coloring of `process.versions` (Ben Noordhuis) [#17861](https://github.com/nodejs/node/pull/17861) +* [[`bb9219bd19`](https://github.com/nodejs/node/commit/bb9219bd19)] - **src**: update make for new code coverage locations (Michael Dawson) [#17987](https://github.com/nodejs/node/pull/17987) +* [[`aa7519095c`](https://github.com/nodejs/node/commit/aa7519095c)] - **src**: remove duplicate words in comments (Tobias Nießen) [#17939](https://github.com/nodejs/node/pull/17939) +* [[`f9c84c557f`](https://github.com/nodejs/node/commit/f9c84c557f)] - **src**: silence http2 -Wunused-result warnings (cjihrig) [#17954](https://github.com/nodejs/node/pull/17954) +* [[`7e680807f8`](https://github.com/nodejs/node/commit/7e680807f8)] - **src**: add optional keep-alive object to SetImmediate (Anna Henningsen) [#17183](https://github.com/nodejs/node/pull/17183) +* [[`98dc554a2a`](https://github.com/nodejs/node/commit/98dc554a2a)] - **src**: inline HostentToAddresses() (Ben Noordhuis) [#17860](https://github.com/nodejs/node/pull/17860) +* [[`87b336a2e5`](https://github.com/nodejs/node/commit/87b336a2e5)] - **src**: remove unused GetHostByNameWrap (Ben Noordhuis) [#17860](https://github.com/nodejs/node/pull/17860) +* [[`2aa75a1f0b`](https://github.com/nodejs/node/commit/2aa75a1f0b)] - **src**: remove redundant `JSStream::DoAfterWrite` (Anna Henningsen) [#17713](https://github.com/nodejs/node/pull/17713) +* [[`99c62cc454`](https://github.com/nodejs/node/commit/99c62cc454)] - **src**: remove unused async hooks methods (Anna Henningsen) [#17757](https://github.com/nodejs/node/pull/17757) +* [[`d6c588586a`](https://github.com/nodejs/node/commit/d6c588586a)] - **src**: remove nonexistent method from header file (Anna Henningsen) [#17748](https://github.com/nodejs/node/pull/17748) +* [[`a93ed5c282`](https://github.com/nodejs/node/commit/a93ed5c282)] - **src**: replace SetAccessor w/ SetAccessorProperty (Jure Triglav) [#17665](https://github.com/nodejs/node/pull/17665) +* [[`d84d9be6ef`](https://github.com/nodejs/node/commit/d84d9be6ef)] - **src**: rename `On*` -\> `Emit*` for stream callbacks (Anna Henningsen) [#17701](https://github.com/nodejs/node/pull/17701) +* [[`6f520e3f69`](https://github.com/nodejs/node/commit/6f520e3f69)] - **src**: remove unused strings from env.h (Anna Henningsen) [#17643](https://github.com/nodejs/node/pull/17643) +* [[`6634dc4d0c`](https://github.com/nodejs/node/commit/6634dc4d0c)] - **src**: fix -Wundefined-inline warnings (Ben Noordhuis) [#17649](https://github.com/nodejs/node/pull/17649) +* [[`0c6d9ae72e`](https://github.com/nodejs/node/commit/0c6d9ae72e)] - **src**: fix compile warnings introduced in 73ad3f9bea (Ben Noordhuis) [#17649](https://github.com/nodejs/node/pull/17649) +* [[`008336c920`](https://github.com/nodejs/node/commit/008336c920)] - **src**: minor refactoring to StreamBase writes (Anna Henningsen) [#17564](https://github.com/nodejs/node/pull/17564) +* [[`7ed9e5de39`](https://github.com/nodejs/node/commit/7ed9e5de39)] - **src**: remove `StreamResourc::Cast()` (Anna Henningsen) [#17564](https://github.com/nodejs/node/pull/17564) +* [[`d879b63077`](https://github.com/nodejs/node/commit/d879b63077)] - **src**: make FSEventWrap/StatWatcher::Start more robust (Timothy Gu) [#17432](https://github.com/nodejs/node/pull/17432) +* [[`6ba00b8d48`](https://github.com/nodejs/node/commit/6ba00b8d48)] - **src**: refactor and harden `ProcessEmitWarning()` (Anna Henningsen) [#17420](https://github.com/nodejs/node/pull/17420) +* [[`316da5e667`](https://github.com/nodejs/node/commit/316da5e667)] - **src**: use correct OOB check for IPv6 parsing (Anna Henningsen) [#17470](https://github.com/nodejs/node/pull/17470) +* [[`ca3c2551b6`](https://github.com/nodejs/node/commit/ca3c2551b6)] - **src**: make url host a proper C++ class (Anna Henningsen) [#17470](https://github.com/nodejs/node/pull/17470) +* [[`9f1fe63c39`](https://github.com/nodejs/node/commit/9f1fe63c39)] - **src**: move url internals into anonymous namespace (Anna Henningsen) [#17470](https://github.com/nodejs/node/pull/17470) +* [[`75f99b7c16`](https://github.com/nodejs/node/commit/75f99b7c16)] - **src**: minor cleanups to node_url.cc (Anna Henningsen) [#17470](https://github.com/nodejs/node/pull/17470) +* [[`6bd0aff092`](https://github.com/nodejs/node/commit/6bd0aff092)] - **src**: remove unused variable in node_contextify (Daniel Bevenius) [#17491](https://github.com/nodejs/node/pull/17491) +* [[`df6acf9a84`](https://github.com/nodejs/node/commit/df6acf9a84)] - **src**: remove tracking for exception arrow data (Anna Henningsen) [#17394](https://github.com/nodejs/node/pull/17394) +* [[`e63e4a1fac`](https://github.com/nodejs/node/commit/e63e4a1fac)] - **src**: remove async_hooks destroy timer handle (Anna Henningsen) [#17117](https://github.com/nodejs/node/pull/17117) +* [[`e1f0846a2b`](https://github.com/nodejs/node/commit/e1f0846a2b)] - **src**: introduce internal C++ SetImmediate() mechanism (Anna Henningsen) [#17117](https://github.com/nodejs/node/pull/17117) +* [[`7d1d7390eb`](https://github.com/nodejs/node/commit/7d1d7390eb)] - **src**: fix inspector nullptr deref on abrupt exit (Ben Noordhuis) [#17577](https://github.com/nodejs/node/pull/17577) +* [[`c5c4a534d1`](https://github.com/nodejs/node/commit/c5c4a534d1)] - **(SEMVER-MINOR)** **stream**: rm {writeable/readable}State.length (Calvin Metcalf) [#12857](https://github.com/nodejs/node/pull/12857) +* [[`4b0c8759d3`](https://github.com/nodejs/node/commit/4b0c8759d3)] - **(SEMVER-MINOR)** **stream**: add flow and buffer properties to streams (Calvin Metcalf) [#12855](https://github.com/nodejs/node/pull/12855) +* [[`757e685803`](https://github.com/nodejs/node/commit/757e685803)] - **stream**: remove `undefined` check (Anna Henningsen) [#17644](https://github.com/nodejs/node/pull/17644) +* [[`b313e81783`](https://github.com/nodejs/node/commit/b313e81783)] - **test**: fix flaky test-http-pipeline-flood (Anatoli Papirovski) [#17955](https://github.com/nodejs/node/pull/17955) +* [[`51eab4b005`](https://github.com/nodejs/node/commit/51eab4b005)] - **test**: rename regression tests (Tobias Nießen) [#17948](https://github.com/nodejs/node/pull/17948) +* [[`8806e54c24`](https://github.com/nodejs/node/commit/8806e54c24)] - **test**: fix flaky test-http-highwatermark (Anatoli Papirovski) [#17949](https://github.com/nodejs/node/pull/17949) +* [[`3399e8ac5a`](https://github.com/nodejs/node/commit/3399e8ac5a)] - **test**: fix flaky test-pipe-unref (Anatoli Papirovski) [#17950](https://github.com/nodejs/node/pull/17950) +* [[`79980582b4`](https://github.com/nodejs/node/commit/79980582b4)] - **test**: fix flaky http-writable-true-after-close (Anatoli Papirovski) [#17952](https://github.com/nodejs/node/pull/17952) +* [[`591dd4e398`](https://github.com/nodejs/node/commit/591dd4e398)] - **test**: fix crypto test case to use correct encoding (Tobias Nießen) [#17956](https://github.com/nodejs/node/pull/17956) +* [[`f87a1a6ca8`](https://github.com/nodejs/node/commit/f87a1a6ca8)] - **test**: simplify test-buffer-slice.js (Weijia Wang) [#17962](https://github.com/nodejs/node/pull/17962) +* [[`3cc9882e8c`](https://github.com/nodejs/node/commit/3cc9882e8c)] - **test**: fix flaky test-resolve-async (Anatoli Papirovski) [#17957](https://github.com/nodejs/node/pull/17957) +* [[`3927c6f64e`](https://github.com/nodejs/node/commit/3927c6f64e)] - **test**: improve readability of some crypto tests (Tobias Nießen) [#17904](https://github.com/nodejs/node/pull/17904) +* [[`2f4da8b801`](https://github.com/nodejs/node/commit/2f4da8b801)] - **test**: use countdown in test file (sreepurnajasti) [#17874](https://github.com/nodejs/node/pull/17874) +* [[`ef533c99ba`](https://github.com/nodejs/node/commit/ef533c99ba)] - **test**: add hasCrypto when using binding('crypto') (Daniel Bevenius) [#17867](https://github.com/nodejs/node/pull/17867) +* [[`421eb750b2`](https://github.com/nodejs/node/commit/421eb750b2)] - **test**: improve to use template string (sreepurnajasti) [#17895](https://github.com/nodejs/node/pull/17895) +* [[`275970973e`](https://github.com/nodejs/node/commit/275970973e)] - **test**: replace map() with forEach() where appropriate (Rich Trott) [#17858](https://github.com/nodejs/node/pull/17858) +* [[`f25bab5606`](https://github.com/nodejs/node/commit/f25bab5606)] - **test**: fix flaky test-benchmark-fs (Rich Trott) [#17885](https://github.com/nodejs/node/pull/17885) +* [[`411e7724d4`](https://github.com/nodejs/node/commit/411e7724d4)] - **test**: make test-tls-invoke-queued use public API (Anna Henningsen) [#17864](https://github.com/nodejs/node/pull/17864) +* [[`1dd859d413`](https://github.com/nodejs/node/commit/1dd859d413)] - **test**: refactor test-tls-securepair-fiftharg (Anna Henningsen) [#17836](https://github.com/nodejs/node/pull/17836) +* [[`8b666d61c7`](https://github.com/nodejs/node/commit/8b666d61c7)] - **test**: reduce scope of variable in common module (Rich Trott) [#17830](https://github.com/nodejs/node/pull/17830) +* [[`9110654965`](https://github.com/nodejs/node/commit/9110654965)] - **test**: remove undefined function (Rich Trott) [#17845](https://github.com/nodejs/node/pull/17845) +* [[`ca35d08291`](https://github.com/nodejs/node/commit/ca35d08291)] - **test**: remove ambiguous error messages from test_error (Nicholas Drane) [#17812](https://github.com/nodejs/node/pull/17812) +* [[`ee4cbac52b`](https://github.com/nodejs/node/commit/ee4cbac52b)] - **test**: fix unreliable async-hooks/test-signalwrap (Rich Trott) [#17827](https://github.com/nodejs/node/pull/17827) +* [[`fea5d08d65`](https://github.com/nodejs/node/commit/fea5d08d65)] - **test**: fix flaky test-benchmark-fs (Rich Trott) [#17853](https://github.com/nodejs/node/pull/17853) +* [[`ded097a2bb`](https://github.com/nodejs/node/commit/ded097a2bb)] - **test**: use common module API in test-child-process-exec-stdout-stderr-data-string (sreepurnajasti) [#17751](https://github.com/nodejs/node/pull/17751) +* [[`06862f0c32`](https://github.com/nodejs/node/commit/06862f0c32)] - **test**: do not open fixture files for writing (Rich Trott) [#17810](https://github.com/nodejs/node/pull/17810) +* [[`e9ace7e4dd`](https://github.com/nodejs/node/commit/e9ace7e4dd)] - **test**: do not open fixture files for writing (Rich Trott) [#17808](https://github.com/nodejs/node/pull/17808) +* [[`f79d2efedb`](https://github.com/nodejs/node/commit/f79d2efedb)] - **test**: use valid authentication tag length (Tobias Nießen) [#17566](https://github.com/nodejs/node/pull/17566) +* [[`112b655107`](https://github.com/nodejs/node/commit/112b655107)] - **test**: improve flaky test-listen-fd-ebadf.js (Rich Trott) [#17797](https://github.com/nodejs/node/pull/17797) +* [[`dce7d7fc64`](https://github.com/nodejs/node/commit/dce7d7fc64)] - **test**: refactor test-repl-definecommand (Rich Trott) [#17795](https://github.com/nodejs/node/pull/17795) +* [[`60ae55680c`](https://github.com/nodejs/node/commit/60ae55680c)] - **test**: refactor test-net-connect-buffer (Anna Henningsen) [#17710](https://github.com/nodejs/node/pull/17710) +* [[`c9539678ca`](https://github.com/nodejs/node/commit/c9539678ca)] - **test**: increase diffie-hellman test coverage (Leko) [#17728](https://github.com/nodejs/node/pull/17728) +* [[`6d15185235`](https://github.com/nodejs/node/commit/6d15185235)] - **test**: increase pbkdf2 test coverage (Leko) [#17730](https://github.com/nodejs/node/pull/17730) +* [[`dd14004eed`](https://github.com/nodejs/node/commit/dd14004eed)] - **test**: fix typo in test-inspector-cluster-port-clash.js (Rich Trott) [#17782](https://github.com/nodejs/node/pull/17782) +* [[`5a9694eb60`](https://github.com/nodejs/node/commit/5a9694eb60)] - **test**: change callback function to arrow function (rt33) [#17734](https://github.com/nodejs/node/pull/17734) +* [[`305dd5671c`](https://github.com/nodejs/node/commit/305dd5671c)] - **test**: add test for postmortem metadata validation (cjihrig) [#17685](https://github.com/nodejs/node/pull/17685) +* [[`d9190c17ed`](https://github.com/nodejs/node/commit/d9190c17ed)] - **test**: Use countdown in test file (sreepurnajasti) [#17646](https://github.com/nodejs/node/pull/17646) +* [[`46f8a9eddc`](https://github.com/nodejs/node/commit/46f8a9eddc)] - **test**: update test-http-content-length to use countdown (Bamieh) [#17201](https://github.com/nodejs/node/pull/17201) +* [[`373d5df3b7`](https://github.com/nodejs/node/commit/373d5df3b7)] - **test**: coverage for emitExperimentalWarning (Mithun Sasidharan) [#17635](https://github.com/nodejs/node/pull/17635) +* [[`bc45354cce`](https://github.com/nodejs/node/commit/bc45354cce)] - **test**: change callback function to arrow function (routerman) [#17697](https://github.com/nodejs/node/pull/17697) +* [[`d48a1b99ee`](https://github.com/nodejs/node/commit/d48a1b99ee)] - **test**: change callback function to arrow function (you12724) [#17698](https://github.com/nodejs/node/pull/17698) +* [[`a9d83ce9e0`](https://github.com/nodejs/node/commit/a9d83ce9e0)] - **test**: change callback function to arrow function (Shinya Kanamaru) [#17699](https://github.com/nodejs/node/pull/17699) +* [[`bdddb82595`](https://github.com/nodejs/node/commit/bdddb82595)] - **test**: check socketOnDrain where needPause is false (Leko) [#17654](https://github.com/nodejs/node/pull/17654) +* [[`b8265285ff`](https://github.com/nodejs/node/commit/b8265285ff)] - **test**: fix flaky test-benchmark-misc (Rich Trott) [#17686](https://github.com/nodejs/node/pull/17686) +* [[`b1fd50a773`](https://github.com/nodejs/node/commit/b1fd50a773)] - **test**: remove literals that obscure assert messages (Rich Trott) [#17642](https://github.com/nodejs/node/pull/17642) +* [[`f16eca4383`](https://github.com/nodejs/node/commit/f16eca4383)] - **test**: improve coverage for util.promisify (Mithun Sasidharan) [#17591](https://github.com/nodejs/node/pull/17591) +* [[`97eaaf907f`](https://github.com/nodejs/node/commit/97eaaf907f)] - **test**: remove unused disposed_ variable (Daniel Bevenius) [#17628](https://github.com/nodejs/node/pull/17628) +* [[`cc683bd0cb`](https://github.com/nodejs/node/commit/cc683bd0cb)] - **test**: expand test-https-keep-alive-large-write (Anna Henningsen) [#17564](https://github.com/nodejs/node/pull/17564) +* [[`6cb4cc2f1c`](https://github.com/nodejs/node/commit/6cb4cc2f1c)] - **test**: fix flaky test-child-process-pass-fd (Rich Trott) [#17598](https://github.com/nodejs/node/pull/17598) +* [[`5cd08d3a59`](https://github.com/nodejs/node/commit/5cd08d3a59)] - **test**: add unhandled rejection guard (babygoat) [#17275](https://github.com/nodejs/node/pull/17275) +* [[`b379d8d105`](https://github.com/nodejs/node/commit/b379d8d105)] - **test**: improve crypto/random.js coverage (Leko) [#17555](https://github.com/nodejs/node/pull/17555) +* [[`bc7dc65229`](https://github.com/nodejs/node/commit/bc7dc65229)] - **test**: add test description to fs.readFile tests (Jamie Davis) [#17610](https://github.com/nodejs/node/pull/17610) +* [[`70588f7f21`](https://github.com/nodejs/node/commit/70588f7f21)] - **test**: simplify common.expectsError (Ruben Bridgewater) [#17616](https://github.com/nodejs/node/pull/17616) +* [[`fb640c66cb`](https://github.com/nodejs/node/commit/fb640c66cb)] - **timers**: remove domain enter and exit (Anatoli Papirovski) [#17880](https://github.com/nodejs/node/pull/17880) +* [[`3997617869`](https://github.com/nodejs/node/commit/3997617869)] - **tls**: set servername on client side too (James M Snell) [#17935](https://github.com/nodejs/node/pull/17935) +* [[`e69ea78974`](https://github.com/nodejs/node/commit/e69ea78974)] - **tls**: fix SNICallback without .server option (Anna Henningsen) [#17835](https://github.com/nodejs/node/pull/17835) +* [[`b44f245b14`](https://github.com/nodejs/node/commit/b44f245b14)] - **tls**: comment about old-style errors (xortiz) [#17759](https://github.com/nodejs/node/pull/17759) +* [[`41702ef457`](https://github.com/nodejs/node/commit/41702ef457)] - **tls**: unconsume stream on destroy (Anna Henningsen) [#17478](https://github.com/nodejs/node/pull/17478) +* [[`5514330406`](https://github.com/nodejs/node/commit/5514330406)] - **tls**: use correct class name in deprecation message (Anna Henningsen) [#17561](https://github.com/nodejs/node/pull/17561) +* [[`4dacff72b5`](https://github.com/nodejs/node/commit/4dacff72b5)] - **tools**: do not override V8's gitignore (Yang Guo) [#18010](https://github.com/nodejs/node/pull/18010) +* [[`adc59a3e71`](https://github.com/nodejs/node/commit/adc59a3e71)] - **tools**: host remark-preset-lint-node in-tree (Jon Moss) [#17441](https://github.com/nodejs/node/pull/17441) +* [[`c91a7c09ae`](https://github.com/nodejs/node/commit/c91a7c09ae)] - **tools**: add check for using process.binding crypto (Daniel Bevenius) [#17867](https://github.com/nodejs/node/pull/17867) +* [[`4391ea4a57`](https://github.com/nodejs/node/commit/4391ea4a57)] - **tools**: enable array-callback-return ESLint rule (Rich Trott) [#17858](https://github.com/nodejs/node/pull/17858) +* [[`b89cda4cbd`](https://github.com/nodejs/node/commit/b89cda4cbd)] - **tools**: fix AttributeError: \_\_exit\_\_ on Python 2.6 (Dmitriy Kasyanov) [#17663](https://github.com/nodejs/node/pull/17663) +* [[`2d07243cac`](https://github.com/nodejs/node/commit/2d07243cac)] - **tools**: autofixer for lowercase-name-for-primitive (Shobhit Chittora) [#17715](https://github.com/nodejs/node/pull/17715) +* [[`7ef876d89d`](https://github.com/nodejs/node/commit/7ef876d89d)] - **tools**: fix man pages linking regex (Diego Rodríguez Baquero) [#17724](https://github.com/nodejs/node/pull/17724) +* [[`6531401cde`](https://github.com/nodejs/node/commit/6531401cde)] - **tools**: add number-isnan rule (Jon Moss) [#17556](https://github.com/nodejs/node/pull/17556) +* [[`eaa2d9116a`](https://github.com/nodejs/node/commit/eaa2d9116a)] - **tools**: simplify lowercase-name-for-primitive rule (cjihrig) [#17653](https://github.com/nodejs/node/pull/17653) +* [[`3ad8cf14f5`](https://github.com/nodejs/node/commit/3ad8cf14f5)] - **tools**: add lowercase-name-for-primitive eslint rule (Weijia Wang) [#17568](https://github.com/nodejs/node/pull/17568) +* [[`7bf6be0b7c`](https://github.com/nodejs/node/commit/7bf6be0b7c)] - **trace_events**: stop tracing agent in process.exit() (Andreas Madsen) [#18005](https://github.com/nodejs/node/pull/18005) +* [[`ed7f59a1ee`](https://github.com/nodejs/node/commit/ed7f59a1ee)] - **url**: added url fragment lookup table (Hakan Kimeiga) [#17627](https://github.com/nodejs/node/pull/17627) +* [[`28ef3de2ba`](https://github.com/nodejs/node/commit/28ef3de2ba)] - **url**: added space to class string of iterator objects (Haejin Jo) [#17558](https://github.com/nodejs/node/pull/17558) +* [[`6d9b1e4c83`](https://github.com/nodejs/node/commit/6d9b1e4c83)] - **util**: allow wildcards in NODE_DEBUG variable (Tyler) [#17609](https://github.com/nodejs/node/pull/17609) +* [[`6cc622f01b`](https://github.com/nodejs/node/commit/6cc622f01b)] - **vm**: allow modifying context name in inspector (Timothy Gu) [#17720](https://github.com/nodejs/node/pull/17720) +* [[`e2767114ff`](https://github.com/nodejs/node/commit/e2767114ff)] - **vm**: never abort on caught syntax error (Anna Henningsen) [#17394](https://github.com/nodejs/node/pull/17394) +* [[`7bf4102db9`](https://github.com/nodejs/node/commit/7bf4102db9)] - **win, build**: fix without-intl option (Bartosz Sosnowski) [#17614](https://github.com/nodejs/node/pull/17614) +* [[`584e74d8cc`](https://github.com/nodejs/node/commit/584e74d8cc)] - **(SEMVER-MINOR)** **zlib**: add ArrayBuffer support (Jem Bezooyen) [#16042](https://github.com/nodejs/node/pull/16042) + <a id="9.3.0"></a> ## 2017-12-12, Version 9.3.0 (Current), @MylesBorins @@ -188,8 +464,8 @@ * [[`b87030c5cf`](https://github.com/nodejs/node/commit/b87030c5cf)] - **doc**: correct the wrong added meta data (Gaara) [#17072](https://github.com/nodejs/node/pull/17072) * [[`73295370cc`](https://github.com/nodejs/node/commit/73295370cc)] - **doc**: document fs.realpath.native() (Ben Noordhuis) [#17059](https://github.com/nodejs/node/pull/17059) * [[`4bdd05dd84`](https://github.com/nodejs/node/commit/4bdd05dd84)] - **doc**: add Table of Contents to Cpp style guide (Franziska Hinkelmann) [#17052](https://github.com/nodejs/node/pull/17052) -* [[`7d49bd0045`](https://github.com/nodejs/node/commit/7d49bd0045)] - **doc**: add `clientCertEngine` to docs (Rich Trott) -* [[`7594032fac`](https://github.com/nodejs/node/commit/7594032fac)] - **doc**: add hashseed to collaborators (Yang Guo) +* [[`7d49bd0045`](https://github.com/nodejs/node/commit/7d49bd0045)] - **doc**: add `clientCertEngine` to docs (Rich Trott) +* [[`7594032fac`](https://github.com/nodejs/node/commit/7594032fac)] - **doc**: add hashseed to collaborators (Yang Guo) * [[`a256482318`](https://github.com/nodejs/node/commit/a256482318)] - **doc,test**: remove unnecessary await with return instances (Rich Trott) [#17265](https://github.com/nodejs/node/pull/17265) * [[`bccdea623d`](https://github.com/nodejs/node/commit/bccdea623d)] - **doc,win**: clarify WSL support (João Reis) [#17008](https://github.com/nodejs/node/pull/17008) * [[`9b16e15f44`](https://github.com/nodejs/node/commit/9b16e15f44)] - **domain**: re-implement domain over async_hook (vladimir) [#16222](https://github.com/nodejs/node/pull/16222) @@ -392,14 +668,14 @@ * [[`70060eef65`](https://github.com/nodejs/node/commit/70060eef65)] - **test**: --enable-static linked executable (Daniel Bevenius) [#14986](https://github.com/nodejs/node/pull/14986) * [[`113dd2b573`](https://github.com/nodejs/node/commit/113dd2b573)] - **test**: add basic WebAssembly test (Steve Kinney) [#16760](https://github.com/nodejs/node/pull/16760) * [[`f80cf5a33d`](https://github.com/nodejs/node/commit/f80cf5a33d)] - **test**: add coverage to tty module (cjihrig) [#16959](https://github.com/nodejs/node/pull/16959) -* [[`121245f25f`](https://github.com/nodejs/node/commit/121245f25f)] - **test**: add tls clientcertengine tests (Rich Trott) -* [[`3b1db7f54b`](https://github.com/nodejs/node/commit/3b1db7f54b)] - **test**: flag known flake (Refael Ackermann) +* [[`121245f25f`](https://github.com/nodejs/node/commit/121245f25f)] - **test**: add tls clientcertengine tests (Rich Trott) +* [[`3b1db7f54b`](https://github.com/nodejs/node/commit/3b1db7f54b)] - **test**: flag known flake (Refael Ackermann) * [[`0093840044`](https://github.com/nodejs/node/commit/0093840044)] - **test,doc**: do not indicate that non-functions "return" values (Rich Trott) [#17267](https://github.com/nodejs/node/pull/17267) * [[`b6929e2aa9`](https://github.com/nodejs/node/commit/b6929e2aa9)] - **test,doc**: document where common modules go (Gibson Fahnestock) [#16089](https://github.com/nodejs/node/pull/16089) * [[`89d31ee048`](https://github.com/nodejs/node/commit/89d31ee048)] - **timers**: improvements to TimersList management (Anatoli Papirovski) [#17429](https://github.com/nodejs/node/pull/17429) * [[`bd79c3788b`](https://github.com/nodejs/node/commit/bd79c3788b)] - **timers**: clean up for readability (Anatoli Papirovski) [#17279](https://github.com/nodejs/node/pull/17279) * [[`fd501b31c6`](https://github.com/nodejs/node/commit/fd501b31c6)] - **timers**: cross JS/C++ border less frequently (Anna Henningsen) [#17064](https://github.com/nodejs/node/pull/17064) -* [[`33c1e8b3d5`](https://github.com/nodejs/node/commit/33c1e8b3d5)] - **tls**: implement clientCertEngine option (joelostrowski) +* [[`33c1e8b3d5`](https://github.com/nodejs/node/commit/33c1e8b3d5)] - **tls**: implement clientCertEngine option (joelostrowski) * [[`f7a1e39139`](https://github.com/nodejs/node/commit/f7a1e39139)] - **tools**: simplify no-let-in-for-declaration rule (cjihrig) [#17572](https://github.com/nodejs/node/pull/17572) * [[`e157e1c922`](https://github.com/nodejs/node/commit/e157e1c922)] - **tools**: simplify buffer-constructor rule (cjihrig) [#17572](https://github.com/nodejs/node/pull/17572) * [[`01e7b446d1`](https://github.com/nodejs/node/commit/01e7b446d1)] - **tools**: simplify prefer-assert-methods rule (cjihrig) [#17572](https://github.com/nodejs/node/pull/17572) diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js index 21598efa65f..eb90c28b646 100644 --- a/lib/_stream_readable.js +++ b/lib/_stream_readable.js @@ -267,7 +267,6 @@ function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { function addChunk(stream, state, chunk, addToFront) { if (state.flowing && state.length === 0 && !state.sync) { stream.emit('data', chunk); - stream.read(0); } else { // update the buffer info. state.length += state.objectMode ? 1 : chunk.length; @@ -496,7 +495,11 @@ function onEofChunk(stream, state) { state.ended = true; // emit 'readable' now to make sure it gets picked up. - emitReadable(stream); + state.needReadable = false; + if (!state.emittedReadable) { + state.emittedReadable = true; + emitReadable_(stream); + } } // Don't emit readable right away in sync mode, because this can trigger @@ -508,16 +511,15 @@ function emitReadable(stream) { if (!state.emittedReadable) { debug('emitReadable', state.flowing); state.emittedReadable = true; - if (state.sync) - process.nextTick(emitReadable_, stream); - else - emitReadable_(stream); + process.nextTick(emitReadable_, stream); } } function emitReadable_(stream) { + var state = stream._readableState; debug('emit readable'); stream.emit('readable'); + state.needReadable = !state.flowing && !state.ended; flow(stream); } @@ -537,7 +539,7 @@ function maybeReadMore(stream, state) { function maybeReadMore_(stream, state) { var len = state.length; - while (!state.reading && !state.flowing && !state.ended && + while (!state.reading && !state.ended && state.length < state.highWaterMark) { debug('maybeReadMore read 0'); stream.read(0); @@ -644,6 +646,7 @@ Readable.prototype.pipe = function(dest, pipeOpts) { debug('ondata'); increasedAwaitDrain = false; var ret = dest.write(chunk); + debug('dest.write', ret); if (false === ret && !increasedAwaitDrain) { // If the user unpiped during `dest.write()`, it is possible // to get stuck in a permanently paused state if that write @@ -824,8 +827,8 @@ function resume(stream, state) { } function resume_(stream, state) { + debug('resume', state.reading); if (!state.reading) { - debug('resume read 0'); stream.read(0); } @@ -1087,6 +1090,7 @@ function copyFromBuffer(n, list) { function endReadable(stream) { var state = stream._readableState; + debug('endReadable', state.endEmitted); if (!state.endEmitted) { state.ended = true; process.nextTick(endReadableNT, state, stream); @@ -1094,6 +1098,8 @@ function endReadable(stream) { } function endReadableNT(state, stream) { + debug('endReadableNT', state.endEmitted, state.length); + // Check that we didn't get one last unshift. if (!state.endEmitted && state.length === 0) { state.endEmitted = true; diff --git a/lib/assert.js b/lib/assert.js index 4da17b18c51..1dd58230fd4 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -33,6 +33,8 @@ const trace_mgr = require('trace_mgr'); //ENABLE_TTD const assert = module.exports = ok; +const NO_EXCEPTION_SENTINEL = {}; + // All of the following functions must throw an AssertionError // when a corresponding condition is not met, with a message that // may be undefined if not provided. All assertion methods provide @@ -257,6 +259,7 @@ function getActual(block) { } catch (e) { return e; } + return NO_EXCEPTION_SENTINEL; } // Expected to throw an error. @@ -274,7 +277,7 @@ assert.throws = function throws(block, error, message) { error = null; } - if (actual === undefined) { + if (actual === NO_EXCEPTION_SENTINEL) { let details = ''; if (error && error.name) { details += ` (${error.name})`; @@ -295,7 +298,7 @@ assert.throws = function throws(block, error, message) { assert.doesNotThrow = function doesNotThrow(block, error, message) { const actual = getActual(block); - if (actual === undefined) + if (actual === NO_EXCEPTION_SENTINEL) return; if (typeof error === 'string') { @@ -309,7 +312,7 @@ assert.doesNotThrow = function doesNotThrow(block, error, message) { actual, expected: error, operator: 'doesNotThrow', - message: `Got unwanted exception${details}\n${actual.message}`, + message: `Got unwanted exception${details}\n${actual && actual.message}`, stackStartFn: doesNotThrow }); } diff --git a/lib/internal/errors.js b/lib/internal/errors.js index 505f2dd1bba..a057e628d90 100644 --- a/lib/internal/errors.js +++ b/lib/internal/errors.js @@ -437,6 +437,9 @@ E('ERR_MODULE_RESOLUTION_LEGACY', '%s not found by import in %s.' + E('ERR_MULTIPLE_CALLBACK', 'Callback called multiple times'); E('ERR_NAPI_CONS_FUNCTION', 'Constructor must be a function'); E('ERR_NAPI_CONS_PROTOTYPE_OBJECT', 'Constructor.prototype must be an object'); +E('ERR_NAPI_INVALID_DATAVIEW_ARGS', + 'byte_offset + byte_length should be less than or eqaul to the size in ' + + 'bytes of the array passed in'); E('ERR_NO_CRYPTO', 'Node.js is not compiled with OpenSSL crypto support'); E('ERR_NO_ICU', '%s is not supported on Node.js compiled without ICU'); E('ERR_NO_LONGER_SUPPORTED', '%s is no longer supported'); diff --git a/lib/perf_hooks.js b/lib/perf_hooks.js index 7e1d085b525..4a05f7ccba7 100644 --- a/lib/perf_hooks.js +++ b/lib/perf_hooks.js @@ -66,6 +66,70 @@ const observerableTypes = [ 'http2' ]; +const IDX_STREAM_STATS_ID = 0; +const IDX_STREAM_STATS_TIMETOFIRSTBYTE = 1; +const IDX_STREAM_STATS_TIMETOFIRSTHEADER = 2; +const IDX_STREAM_STATS_TIMETOFIRSTBYTESENT = 3; +const IDX_STREAM_STATS_SENTBYTES = 4; +const IDX_STREAM_STATS_RECEIVEDBYTES = 5; + +const IDX_SESSION_STATS_TYPE = 0; +const IDX_SESSION_STATS_PINGRTT = 1; +const IDX_SESSION_STATS_FRAMESRECEIVED = 2; +const IDX_SESSION_STATS_FRAMESSENT = 3; +const IDX_SESSION_STATS_STREAMCOUNT = 4; +const IDX_SESSION_STATS_STREAMAVERAGEDURATION = 5; +const IDX_SESSION_STATS_DATA_SENT = 6; +const IDX_SESSION_STATS_DATA_RECEIVED = 7; +const IDX_SESSION_STATS_MAX_CONCURRENT_STREAMS = 8; + +let sessionStats; +let streamStats; + +function collectHttp2Stats(entry) { + switch (entry.name) { + case 'Http2Stream': + if (streamStats === undefined) + streamStats = process.binding('http2').streamStats; + entry.id = + streamStats[IDX_STREAM_STATS_ID] >>> 0; + entry.timeToFirstByte = + streamStats[IDX_STREAM_STATS_TIMETOFIRSTBYTE]; + entry.timeToFirstHeader = + streamStats[IDX_STREAM_STATS_TIMETOFIRSTHEADER]; + entry.timeToFirstByteSent = + streamStats[IDX_STREAM_STATS_TIMETOFIRSTBYTESENT]; + entry.bytesWritten = + streamStats[IDX_STREAM_STATS_SENTBYTES]; + entry.bytesRead = + streamStats[IDX_STREAM_STATS_RECEIVEDBYTES]; + break; + case 'Http2Session': + if (sessionStats === undefined) + sessionStats = process.binding('http2').sessionStats; + entry.type = + sessionStats[IDX_SESSION_STATS_TYPE] >>> 0 === 0 ? 'server' : 'client'; + entry.pingRTT = + sessionStats[IDX_SESSION_STATS_PINGRTT]; + entry.framesReceived = + sessionStats[IDX_SESSION_STATS_FRAMESRECEIVED]; + entry.framesSent = + sessionStats[IDX_SESSION_STATS_FRAMESSENT]; + entry.streamCount = + sessionStats[IDX_SESSION_STATS_STREAMCOUNT]; + entry.streamAverageDuration = + sessionStats[IDX_SESSION_STATS_STREAMAVERAGEDURATION]; + entry.bytesWritten = + sessionStats[IDX_SESSION_STATS_DATA_SENT]; + entry.bytesRead = + sessionStats[IDX_SESSION_STATS_DATA_RECEIVED]; + entry.maxConcurrentStreams = + sessionStats[IDX_SESSION_STATS_MAX_CONCURRENT_STREAMS]; + break; + } +} + + let errors; function lazyErrors() { if (errors === undefined) @@ -467,6 +531,10 @@ function doNotify() { // Set up the callback used to receive PerformanceObserver notifications function observersCallback(entry) { const type = mapTypes(entry.entryType); + + if (type === NODE_PERFORMANCE_ENTRY_TYPE_HTTP2) + collectHttp2Stats(entry); + performance[kInsertEntry](entry); const list = getObserversList(type); diff --git a/node.gyp b/node.gyp index 885e4d92eaf..409a70e31e1 100644 --- a/node.gyp +++ b/node.gyp @@ -977,7 +977,7 @@ [ 'OS=="win" and node_target_type!="static_library"', { 'libraries': [ '<(OBJ_PATH)<(OBJ_SEPARATOR)backtrace_win32.<(OBJ_SUFFIX)', - ], + ], 'conditions': [ # this is only necessary for chakra on windows because chakra is dynamically linked on windows [ 'node_engine=="chakracore"', { diff --git a/src/node_api.cc b/src/node_api.cc index 5f0e81b0132..2101fcba020 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -3168,6 +3168,14 @@ napi_status napi_create_dataview(napi_env env, RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg); v8::Local<v8::ArrayBuffer> buffer = value.As<v8::ArrayBuffer>(); + if (byte_length + byte_offset > buffer->ByteLength()) { + napi_throw_range_error( + env, + "ERR_NAPI_INVALID_DATAVIEW_ARGS", + "byte_offset + byte_length should be less than or " + "equal to the size in bytes of the array passed in"); + return napi_set_last_error(env, napi_pending_exception); + } v8::Local<v8::DataView> DataView = v8::DataView::New(buffer, byte_offset, byte_length); diff --git a/src/node_http2.cc b/src/node_http2.cc index ecb565ffa5e..d766db8b105 100644 --- a/src/node_http2.cc +++ b/src/node_http2.cc @@ -478,6 +478,8 @@ Http2Session::Callbacks::Callbacks(bool kHasGetPaddingCallback) { callbacks, OnSendData); nghttp2_session_callbacks_set_on_invalid_frame_recv_callback( callbacks, OnInvalidFrame); + nghttp2_session_callbacks_set_on_frame_send_callback( + callbacks, OnFrameSent); if (kHasGetPaddingCallback) { nghttp2_session_callbacks_set_select_padding_callback( @@ -566,28 +568,35 @@ inline void Http2Stream::EmitStatistics() { if (!HasHttp2Observer(env())) return; Http2StreamPerformanceEntry* entry = - new Http2StreamPerformanceEntry(env(), statistics_); + new Http2StreamPerformanceEntry(env(), id_, statistics_); env()->SetImmediate([](Environment* env, void* data) { - Local<Context> context = env->context(); Http2StreamPerformanceEntry* entry = static_cast<Http2StreamPerformanceEntry*>(data); if (HasHttp2Observer(env)) { - Local<Object> obj = entry->ToObject(); - v8::PropertyAttribute attr = - static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete); - obj->DefineOwnProperty( - context, - FIXED_ONE_BYTE_STRING(env->isolate(), "timeToFirstByte"), - Number::New(env->isolate(), - (entry->first_byte() - entry->startTimeNano()) / 1e6), - attr).FromJust(); - obj->DefineOwnProperty( - context, - FIXED_ONE_BYTE_STRING(env->isolate(), "timeToFirstHeader"), - Number::New(env->isolate(), - (entry->first_header() - entry->startTimeNano()) / 1e6), - attr).FromJust(); - entry->Notify(obj); + AliasedBuffer<double, v8::Float64Array>& buffer = + env->http2_state()->stream_stats_buffer; + buffer[IDX_STREAM_STATS_ID] = entry->id(); + if (entry->first_byte() != 0) { + buffer[IDX_STREAM_STATS_TIMETOFIRSTBYTE] = + (entry->first_byte() - entry->startTimeNano()) / 1e6; + } else { + buffer[IDX_STREAM_STATS_TIMETOFIRSTBYTE] = 0; + } + if (entry->first_header() != 0) { + buffer[IDX_STREAM_STATS_TIMETOFIRSTHEADER] = + (entry->first_header() - entry->startTimeNano()) / 1e6; + } else { + buffer[IDX_STREAM_STATS_TIMETOFIRSTHEADER] = 0; + } + if (entry->first_byte_sent() != 0) { + buffer[IDX_STREAM_STATS_TIMETOFIRSTBYTESENT] = + (entry->first_byte_sent() - entry->startTimeNano()) / 1e6; + } else { + buffer[IDX_STREAM_STATS_TIMETOFIRSTBYTESENT] = 0; + } + buffer[IDX_STREAM_STATS_SENTBYTES] = entry->sent_bytes(); + buffer[IDX_STREAM_STATS_RECEIVEDBYTES] = entry->received_bytes(); + entry->Notify(entry->ToObject()); } delete entry; }, static_cast<void*>(entry)); @@ -597,45 +606,25 @@ inline void Http2Session::EmitStatistics() { if (!HasHttp2Observer(env())) return; Http2SessionPerformanceEntry* entry = - new Http2SessionPerformanceEntry(env(), statistics_, TypeName()); + new Http2SessionPerformanceEntry(env(), statistics_, session_type_); env()->SetImmediate([](Environment* env, void* data) { - Local<Context> context = env->context(); Http2SessionPerformanceEntry* entry = static_cast<Http2SessionPerformanceEntry*>(data); if (HasHttp2Observer(env)) { - Local<Object> obj = entry->ToObject(); - v8::PropertyAttribute attr = - static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete); - obj->DefineOwnProperty( - context, - FIXED_ONE_BYTE_STRING(env->isolate(), "type"), - String::NewFromUtf8(env->isolate(), - entry->typeName(), - v8::NewStringType::kInternalized) - .ToLocalChecked(), attr).FromJust(); - if (entry->ping_rtt() != 0) { - obj->DefineOwnProperty( - context, - FIXED_ONE_BYTE_STRING(env->isolate(), "pingRTT"), - Number::New(env->isolate(), entry->ping_rtt() / 1e6), - attr).FromJust(); - } - obj->DefineOwnProperty( - context, - FIXED_ONE_BYTE_STRING(env->isolate(), "framesReceived"), - Integer::NewFromUnsigned(env->isolate(), entry->frame_count()), - attr).FromJust(); - obj->DefineOwnProperty( - context, - FIXED_ONE_BYTE_STRING(env->isolate(), "streamCount"), - Integer::New(env->isolate(), entry->stream_count()), - attr).FromJust(); - obj->DefineOwnProperty( - context, - FIXED_ONE_BYTE_STRING(env->isolate(), "streamAverageDuration"), - Number::New(env->isolate(), entry->stream_average_duration()), - attr).FromJust(); - entry->Notify(obj); + AliasedBuffer<double, v8::Float64Array>& buffer = + env->http2_state()->session_stats_buffer; + buffer[IDX_SESSION_STATS_TYPE] = entry->type(); + buffer[IDX_SESSION_STATS_PINGRTT] = entry->ping_rtt() / 1e6; + buffer[IDX_SESSION_STATS_FRAMESRECEIVED] = entry->frame_count(); + buffer[IDX_SESSION_STATS_FRAMESSENT] = entry->frame_sent(); + buffer[IDX_SESSION_STATS_STREAMCOUNT] = entry->stream_count(); + buffer[IDX_SESSION_STATS_STREAMAVERAGEDURATION] = + entry->stream_average_duration(); + buffer[IDX_SESSION_STATS_DATA_SENT] = entry->data_sent(); + buffer[IDX_SESSION_STATS_DATA_RECEIVED] = entry->data_received(); + buffer[IDX_SESSION_STATS_MAX_CONCURRENT_STREAMS] = + entry->max_concurrent_streams(); + entry->Notify(entry->ToObject()); } delete entry; }, static_cast<void*>(entry)); @@ -701,6 +690,9 @@ inline bool Http2Session::CanAddStream() { inline void Http2Session::AddStream(Http2Stream* stream) { CHECK_GE(++statistics_.stream_count, 0); streams_[stream->id()] = stream; + size_t size = streams_.size(); + if (size > statistics_.max_concurrent_streams) + statistics_.max_concurrent_streams = size; IncrementCurrentSessionMemory(stream->self_size()); } @@ -969,6 +961,14 @@ inline int Http2Session::OnFrameNotSent(nghttp2_session* handle, return 0; } +inline int Http2Session::OnFrameSent(nghttp2_session* handle, + const nghttp2_frame* frame, + void* user_data) { + Http2Session* session = static_cast<Http2Session*>(user_data); + session->statistics_.frame_sent += 1; + return 0; +} + // Called by nghttp2 when a stream closes. inline int Http2Session::OnStreamClose(nghttp2_session* handle, int32_t id, @@ -1046,6 +1046,7 @@ inline int Http2Session::OnDataChunkReceived(nghttp2_session* handle, // If the stream has been destroyed, ignore this chunk if (stream->IsDestroyed()) return 0; + stream->statistics_.received_bytes += len; stream->AddChunk(data, len); } return 0; @@ -1500,6 +1501,7 @@ void Http2Session::SendPendingData() { size_t offset = 0; size_t i = 0; for (const nghttp2_stream_write& write : outgoing_buffers_) { + statistics_.data_sent += write.buf.len; if (write.buf.base == nullptr) { bufs[i++] = uv_buf_init( reinterpret_cast<char*>(outgoing_storage_.data() + offset), @@ -1649,6 +1651,7 @@ void Http2Session::OnStreamReadImpl(ssize_t nread, if (bufs->len > 0) { // Only pass data on if nread > 0 uv_buf_t buf[] { uv_buf_init((*bufs).base, nread) }; + session->statistics_.data_received += nread; ssize_t ret = session->Write(buf, 1); // Note: if ssize_t is not defined (e.g. on Win32), nghttp2 will typedef @@ -2148,6 +2151,8 @@ ssize_t Http2Stream::Provider::FD::OnRead(nghttp2_session* handle, void* user_data) { Http2Session* session = static_cast<Http2Session*>(user_data); Http2Stream* stream = session->FindStream(id); + if (stream->statistics_.first_byte_sent == 0) + stream->statistics_.first_byte_sent = uv_hrtime(); DEBUG_HTTP2SESSION2(session, "reading outbound file data for stream %d", id); CHECK_EQ(id, stream->id()); @@ -2198,6 +2203,7 @@ ssize_t Http2Stream::Provider::FD::OnRead(nghttp2_session* handle, return NGHTTP2_ERR_CALLBACK_FAILURE; } + stream->statistics_.sent_bytes += numchars; return numchars; } @@ -2223,6 +2229,8 @@ ssize_t Http2Stream::Provider::Stream::OnRead(nghttp2_session* handle, Http2Session* session = static_cast<Http2Session*>(user_data); DEBUG_HTTP2SESSION2(session, "reading outbound data for stream %d", id); Http2Stream* stream = GetStream(session, id, source); + if (stream->statistics_.first_byte_sent == 0) + stream->statistics_.first_byte_sent = uv_hrtime(); CHECK_EQ(id, stream->id()); size_t amount = 0; // amount of data being sent in this data frame. @@ -2256,6 +2264,8 @@ ssize_t Http2Stream::Provider::Stream::OnRead(nghttp2_session* handle, if (session->IsDestroyed()) return NGHTTP2_ERR_CALLBACK_FAILURE; } + + stream->statistics_.sent_bytes += amount; return amount; } @@ -2869,6 +2879,10 @@ void Initialize(Local<Object> target, "settingsBuffer", state->settings_buffer.GetJSArray()); SET_STATE_TYPEDARRAY( "optionsBuffer", state->options_buffer.GetJSArray()); + SET_STATE_TYPEDARRAY( + "streamStats", state->stream_stats_buffer.GetJSArray()); + SET_STATE_TYPEDARRAY( + "sessionStats", state->session_stats_buffer.GetJSArray()); #undef SET_STATE_TYPEDARRAY env->set_http2_state(std::move(state)); diff --git a/src/node_http2.h b/src/node_http2.h index 4fc98f0c68a..765f7294768 100644 --- a/src/node_http2.h +++ b/src/node_http2.h @@ -715,8 +715,11 @@ class Http2Stream : public AsyncWrap, struct Statistics { uint64_t start_time; uint64_t end_time; - uint64_t first_header; // Time first header was received - uint64_t first_byte; // Time first data frame byte was received + uint64_t first_header; // Time first header was received + uint64_t first_byte; // Time first DATA frame byte was received + uint64_t first_byte_sent; // Time first DATA frame byte was sent + uint64_t sent_bytes; + uint64_t received_bytes; }; Statistics statistics_ = {}; @@ -949,8 +952,12 @@ class Http2Session : public AsyncWrap { uint64_t start_time; uint64_t end_time; uint64_t ping_rtt; + uint64_t data_sent; + uint64_t data_received; uint32_t frame_count; + uint32_t frame_sent; int32_t stream_count; + size_t max_concurrent_streams; double stream_average_duration; }; @@ -995,6 +1002,10 @@ class Http2Session : public AsyncWrap { const nghttp2_frame* frame, int error_code, void* user_data); + static inline int OnFrameSent( + nghttp2_session* session, + const nghttp2_frame* frame, + void* user_data); static inline int OnStreamClose( nghttp2_session* session, int32_t id, @@ -1115,21 +1126,29 @@ class Http2SessionPerformanceEntry : public PerformanceEntry { Http2SessionPerformanceEntry( Environment* env, const Http2Session::Statistics& stats, - const char* kind) : + nghttp2_session_type type) : PerformanceEntry(env, "Http2Session", "http2", stats.start_time, stats.end_time), ping_rtt_(stats.ping_rtt), + data_sent_(stats.data_sent), + data_received_(stats.data_received), frame_count_(stats.frame_count), + frame_sent_(stats.frame_sent), stream_count_(stats.stream_count), + max_concurrent_streams_(stats.max_concurrent_streams), stream_average_duration_(stats.stream_average_duration), - kind_(kind) { } + session_type_(type) { } uint64_t ping_rtt() const { return ping_rtt_; } + uint64_t data_sent() const { return data_sent_; } + uint64_t data_received() const { return data_received_; } uint32_t frame_count() const { return frame_count_; } + uint32_t frame_sent() const { return frame_sent_; } int32_t stream_count() const { return stream_count_; } + size_t max_concurrent_streams() const { return max_concurrent_streams_; } double stream_average_duration() const { return stream_average_duration_; } - const char* typeName() const { return kind_; } + nghttp2_session_type type() const { return session_type_; } void Notify(Local<Value> obj) { PerformanceEntry::Notify(env(), kind(), obj); @@ -1137,33 +1156,50 @@ class Http2SessionPerformanceEntry : public PerformanceEntry { private: uint64_t ping_rtt_; + uint64_t data_sent_; + uint64_t data_received_; uint32_t frame_count_; + uint32_t frame_sent_; int32_t stream_count_; + size_t max_concurrent_streams_; double stream_average_duration_; - const char* kind_; + nghttp2_session_type session_type_; }; class Http2StreamPerformanceEntry : public PerformanceEntry { public: Http2StreamPerformanceEntry( Environment* env, + int32_t id, const Http2Stream::Statistics& stats) : PerformanceEntry(env, "Http2Stream", "http2", stats.start_time, stats.end_time), + id_(id), first_header_(stats.first_header), - first_byte_(stats.first_byte) { } + first_byte_(stats.first_byte), + first_byte_sent_(stats.first_byte_sent), + sent_bytes_(stats.sent_bytes), + received_bytes_(stats.received_bytes) { } + int32_t id() const { return id_; } uint64_t first_header() const { return first_header_; } uint64_t first_byte() const { return first_byte_; } + uint64_t first_byte_sent() const { return first_byte_sent_; } + uint64_t sent_bytes() const { return sent_bytes_; } + uint64_t received_bytes() const { return received_bytes_; } void Notify(Local<Value> obj) { PerformanceEntry::Notify(env(), kind(), obj); } private: + int32_t id_; uint64_t first_header_; uint64_t first_byte_; + uint64_t first_byte_sent_; + uint64_t sent_bytes_; + uint64_t received_bytes_; }; class Http2Session::Http2Ping : public AsyncWrap { diff --git a/src/node_http2_state.h b/src/node_http2_state.h index af0740c994e..ed88f068a04 100644 --- a/src/node_http2_state.h +++ b/src/node_http2_state.h @@ -61,6 +61,29 @@ namespace http2 { PADDING_BUF_FIELD_COUNT }; + enum Http2StreamStatisticsIndex { + IDX_STREAM_STATS_ID, + IDX_STREAM_STATS_TIMETOFIRSTBYTE, + IDX_STREAM_STATS_TIMETOFIRSTHEADER, + IDX_STREAM_STATS_TIMETOFIRSTBYTESENT, + IDX_STREAM_STATS_SENTBYTES, + IDX_STREAM_STATS_RECEIVEDBYTES, + IDX_STREAM_STATS_COUNT + }; + + enum Http2SessionStatisticsIndex { + IDX_SESSION_STATS_TYPE, + IDX_SESSION_STATS_PINGRTT, + IDX_SESSION_STATS_FRAMESRECEIVED, + IDX_SESSION_STATS_FRAMESSENT, + IDX_SESSION_STATS_STREAMCOUNT, + IDX_SESSION_STATS_STREAMAVERAGEDURATION, + IDX_SESSION_STATS_DATA_SENT, + IDX_SESSION_STATS_DATA_RECEIVED, + IDX_SESSION_STATS_MAX_CONCURRENT_STREAMS, + IDX_SESSION_STATS_COUNT + }; + class http2_state { public: explicit http2_state(v8::Isolate* isolate) : @@ -77,6 +100,16 @@ class http2_state { offsetof(http2_state_internal, stream_state_buffer), IDX_STREAM_STATE_COUNT, root_buffer), + stream_stats_buffer( + isolate, + offsetof(http2_state_internal, stream_stats_buffer), + IDX_STREAM_STATS_COUNT, + root_buffer), + session_stats_buffer( + isolate, + offsetof(http2_state_internal, session_stats_buffer), + IDX_SESSION_STATS_COUNT, + root_buffer), padding_buffer( isolate, offsetof(http2_state_internal, padding_buffer), @@ -97,6 +130,8 @@ class http2_state { AliasedBuffer<uint8_t, v8::Uint8Array> root_buffer; AliasedBuffer<double, v8::Float64Array> session_state_buffer; AliasedBuffer<double, v8::Float64Array> stream_state_buffer; + AliasedBuffer<double, v8::Float64Array> stream_stats_buffer; + AliasedBuffer<double, v8::Float64Array> session_stats_buffer; AliasedBuffer<uint32_t, v8::Uint32Array> padding_buffer; AliasedBuffer<uint32_t, v8::Uint32Array> options_buffer; AliasedBuffer<uint32_t, v8::Uint32Array> settings_buffer; @@ -106,6 +141,8 @@ class http2_state { // doubles first so that they are always sizeof(double)-aligned double session_state_buffer[IDX_SESSION_STATE_COUNT]; double stream_state_buffer[IDX_STREAM_STATE_COUNT]; + double stream_stats_buffer[IDX_STREAM_STATS_COUNT]; + double session_stats_buffer[IDX_SESSION_STATS_COUNT]; uint32_t padding_buffer[PADDING_BUF_FIELD_COUNT]; uint32_t options_buffer[IDX_OPTIONS_FLAGS + 1]; uint32_t settings_buffer[IDX_SETTINGS_COUNT + 1]; diff --git a/src/node_perf.cc b/src/node_perf.cc index 6a59d50fb64..97d3a2d9952 100644 --- a/src/node_perf.cc +++ b/src/node_perf.cc @@ -182,8 +182,9 @@ void SetupPerformanceObservers(const FunctionCallbackInfo<Value>& args) { } // Creates a GC Performance Entry and passes it to observers -void PerformanceGCCallback(Environment* env, void* ptr) { - GCPerformanceEntry* entry = static_cast<GCPerformanceEntry*>(ptr); +void PerformanceGCCallback(uv_async_t* handle) { + GCPerformanceEntry* entry = static_cast<GCPerformanceEntry*>(handle->data); + Environment* env = entry->env(); HandleScope scope(env->isolate()); Local<Context> context = env->context(); @@ -200,6 +201,10 @@ void PerformanceGCCallback(Environment* env, void* ptr) { } delete entry; + auto closeCB = [](uv_handle_t* handle) { + delete reinterpret_cast<uv_async_t*>(handle); + }; + uv_close(reinterpret_cast<uv_handle_t*>(handle), closeCB); } // Marks the start of a GC cycle @@ -216,11 +221,16 @@ void MarkGarbageCollectionEnd(Isolate* isolate, v8::GCCallbackFlags flags, void* data) { Environment* env = static_cast<Environment*>(data); - env->SetImmediate(PerformanceGCCallback, - new GCPerformanceEntry(env, - static_cast<PerformanceGCKind>(type), - performance_last_gc_start_mark_, - PERFORMANCE_NOW())); + uv_async_t* async = new uv_async_t(); + if (uv_async_init(env->event_loop(), async, PerformanceGCCallback)) + return delete async; + uv_unref(reinterpret_cast<uv_handle_t*>(async)); + async->data = + new GCPerformanceEntry(env, + static_cast<PerformanceGCKind>(type), + performance_last_gc_start_mark_, + PERFORMANCE_NOW()); + CHECK_EQ(0, uv_async_send(async)); } diff --git a/test/addons-napi/test_dataview/test.js b/test/addons-napi/test_dataview/test.js index 711ab01ddb3..a6be5849406 100644 --- a/test/addons-napi/test_dataview/test.js +++ b/test/addons-napi/test_dataview/test.js @@ -5,10 +5,20 @@ const assert = require('assert'); // Testing api calls for arrays const test_dataview = require(`./build/${common.buildType}/test_dataview`); -//create dataview -const buffer = new ArrayBuffer(128); -const template = Reflect.construct(DataView, [buffer]); +// Test for creating dataview +{ + const buffer = new ArrayBuffer(128); + const template = Reflect.construct(DataView, [buffer]); -const theDataview = test_dataview.CreateDataView(template); -assert.ok(theDataview instanceof DataView, - `Expect ${theDataview} to be a DataView`); + const theDataview = test_dataview.CreateDataViewFromJSDataView(template); + assert.ok(theDataview instanceof DataView, + `Expect ${theDataview} to be a DataView`); +} + +// Test for creating dataview with invalid range +{ + const buffer = new ArrayBuffer(128); + assert.throws(() => { + test_dataview.CreateDataView(buffer, 10, 200); + }, RangeError); +} diff --git a/test/addons-napi/test_dataview/test_dataview.c b/test/addons-napi/test_dataview/test_dataview.c index 5f95eef0f38..4d29ed07e9e 100644 --- a/test/addons-napi/test_dataview/test_dataview.c +++ b/test/addons-napi/test_dataview/test_dataview.c @@ -3,6 +3,53 @@ #include "../common.h" napi_value CreateDataView(napi_env env, napi_callback_info info) { + size_t argc = 3; + napi_value args [3]; + NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); + + NAPI_ASSERT(env, argc == 3, "Wrong number of arguments"); + + napi_valuetype valuetype0; + napi_value arraybuffer = args[0]; + + NAPI_CALL(env, napi_typeof(env, arraybuffer, &valuetype0)); + NAPI_ASSERT(env, valuetype0 == napi_object, + "Wrong type of arguments. Expects a ArrayBuffer as the first " + "argument."); + + bool is_arraybuffer; + NAPI_CALL(env, napi_is_arraybuffer(env, arraybuffer, &is_arraybuffer)); + NAPI_ASSERT(env, is_arraybuffer, + "Wrong type of arguments. Expects a ArrayBuffer as the first " + "argument."); + + napi_valuetype valuetype1; + NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1)); + + NAPI_ASSERT(env, valuetype1 == napi_number, + "Wrong type of arguments. Expects a number as second argument."); + + size_t byte_offset = 0; + NAPI_CALL(env, napi_get_value_uint32(env, args[1], (uint32_t*)(&byte_offset))); + + napi_valuetype valuetype2; + NAPI_CALL(env, napi_typeof(env, args[2], &valuetype2)); + + NAPI_ASSERT(env, valuetype2 == napi_number, + "Wrong type of arguments. Expects a number as third argument."); + + size_t length = 0; + NAPI_CALL(env, napi_get_value_uint32(env, args[2], (uint32_t*)(&length))); + + napi_value output_dataview; + NAPI_CALL(env, + napi_create_dataview(env, length, arraybuffer, + byte_offset, &output_dataview)); + + return output_dataview; +} + +napi_value CreateDataViewFromJSDataView(napi_env env, napi_callback_info info) { size_t argc = 1; napi_value args [1]; NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL)); @@ -34,12 +81,15 @@ napi_value CreateDataView(napi_env env, napi_callback_info info) { napi_create_dataview(env, length, buffer, byte_offset, &output_dataview)); + return output_dataview; } napi_value Init(napi_env env, napi_value exports) { napi_property_descriptor descriptors[] = { - DECLARE_NAPI_PROPERTY("CreateDataView", CreateDataView) + DECLARE_NAPI_PROPERTY("CreateDataView", CreateDataView), + DECLARE_NAPI_PROPERTY("CreateDataViewFromJSDataView", + CreateDataViewFromJSDataView) }; NAPI_CALL(env, napi_define_properties( diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index 5e76a0a8fc2..4cab6c691a4 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -857,4 +857,16 @@ common.expectsError( message: "message: expected '', not 'foo'" } ); + + // eslint-disable-next-line no-throw-literal + assert.throws(() => { throw undefined; }, /undefined/); + common.expectsError( + // eslint-disable-next-line no-throw-literal + () => assert.doesNotThrow(() => { throw undefined; }), + { + type: assert.AssertionError, + code: 'ERR_ASSERTION', + message: 'Got unwanted exception.\nundefined' + } + ); } diff --git a/test/parallel/test-http-response-statuscode.js b/test/parallel/test-http-response-statuscode.js index 79c3f630544..7e93ad10a9f 100644 --- a/test/parallel/test-http-response-statuscode.js +++ b/test/parallel/test-http-response-statuscode.js @@ -8,14 +8,13 @@ const MAX_REQUESTS = 13; let reqNum = 0; function test(res, header, code) { - const errRegExp = common.expectsError({ + common.expectsError(() => { + res.writeHead(header); + }, { code: 'ERR_HTTP_INVALID_STATUS_CODE', type: RangeError, message: `Invalid status code: ${code}` }); - assert.throws(() => { - res.writeHead(header); - }, errRegExp); } const server = http.Server(common.mustCall(function(req, res) { diff --git a/test/parallel/test-http2-perf_hooks.js b/test/parallel/test-http2-perf_hooks.js index f2ef29cec25..07d9c55ed7e 100644 --- a/test/parallel/test-http2-perf_hooks.js +++ b/test/parallel/test-http2-perf_hooks.js @@ -8,7 +8,7 @@ const h2 = require('http2'); const { PerformanceObserver } = require('perf_hooks'); -const obs = new PerformanceObserver((items) => { +const obs = new PerformanceObserver(common.mustCall((items) => { const entry = items.getEntries()[0]; assert.strictEqual(entry.entryType, 'http2'); assert.strictEqual(typeof entry.startTime, 'number'); @@ -19,6 +19,10 @@ const obs = new PerformanceObserver((items) => { assert.strictEqual(typeof entry.streamAverageDuration, 'number'); assert.strictEqual(typeof entry.streamCount, 'number'); assert.strictEqual(typeof entry.framesReceived, 'number'); + assert.strictEqual(typeof entry.framesSent, 'number'); + assert.strictEqual(typeof entry.bytesWritten, 'number'); + assert.strictEqual(typeof entry.bytesRead, 'number'); + assert.strictEqual(typeof entry.maxConcurrentStreams, 'number'); switch (entry.type) { case 'server': assert.strictEqual(entry.streamCount, 1); @@ -34,12 +38,15 @@ const obs = new PerformanceObserver((items) => { break; case 'Http2Stream': assert.strictEqual(typeof entry.timeToFirstByte, 'number'); + assert.strictEqual(typeof entry.timeToFirstByteSent, 'number'); assert.strictEqual(typeof entry.timeToFirstHeader, 'number'); + assert.strictEqual(typeof entry.bytesWritten, 'number'); + assert.strictEqual(typeof entry.bytesRead, 'number'); break; default: assert.fail('invalid entry name'); } -}); +}, 4)); obs.observe({ entryTypes: ['http2'] }); const body = diff --git a/test/parallel/test-net-end-close.js b/test/parallel/test-net-end-close.js index 44a539a3e80..31c150e09c0 100644 --- a/test/parallel/test-net-end-close.js +++ b/test/parallel/test-net-end-close.js @@ -8,9 +8,9 @@ const uv = process.binding('uv'); const s = new net.Socket({ handle: { readStart: function() { - process.nextTick(() => this.onread(uv.UV_EOF, null)); + setImmediate(() => this.onread(uv.UV_EOF, null)); }, - close: (cb) => process.nextTick(cb) + close: (cb) => setImmediate(cb) }, writable: false }); @@ -18,8 +18,12 @@ assert.strictEqual(s, s.resume()); const events = []; -s.on('end', () => events.push('end')); -s.on('close', () => events.push('close')); +s.on('end', () => { + events.push('end'); +}); +s.on('close', () => { + events.push('close'); +}); process.on('exit', () => { assert.deepStrictEqual(events, [ 'end', 'close' ]); diff --git a/test/parallel/test-performance-gc.js b/test/parallel/test-performance-gc.js index 89a9041c1c1..ec0714ea500 100644 --- a/test/parallel/test-performance-gc.js +++ b/test/parallel/test-performance-gc.js @@ -51,3 +51,13 @@ const kinds = [ // Keep the event loop alive to witness the GC async callback happen. setImmediate(() => setImmediate(() => 0)); } + +// GC should not keep the event loop alive +{ + let didCall = false; + process.on('beforeExit', () => { + assert(!didCall); + didCall = true; + global.gc(); + }); +} diff --git a/test/parallel/test-stream-pipe-await-drain-push-while-write.js b/test/parallel/test-stream-pipe-await-drain-push-while-write.js index adefad70adc..263e6b6801f 100644 --- a/test/parallel/test-stream-pipe-await-drain-push-while-write.js +++ b/test/parallel/test-stream-pipe-await-drain-push-while-write.js @@ -3,32 +3,24 @@ const common = require('../common'); const stream = require('stream'); const assert = require('assert'); -const awaitDrainStates = [ - 1, // after first chunk before callback - 1, // after second chunk before callback - 0 // resolving chunk pushed after first chunk, awaitDrain is decreased -]; - -// A writable stream which pushes data onto the stream which pipes into it, -// but only the first time it's written to. Since it's not paused at this time, -// a second write will occur. If the pipe increases awaitDrain twice, we'll -// never get subsequent chunks because 'drain' is only emitted once. const writable = new stream.Writable({ write: common.mustCall(function(chunk, encoding, cb) { - if (chunk.length === 32 * 1024) { // first chunk - const beforePush = readable._readableState.awaitDrain; - readable.push(Buffer.alloc(34 * 1024)); // above hwm - // We should check if awaitDrain counter is increased. - const afterPush = readable._readableState.awaitDrain; - assert.strictEqual(afterPush - beforePush, 1, - 'Counter is not increased for awaitDrain'); - } - assert.strictEqual( - awaitDrainStates.shift(), readable._readableState.awaitDrain, + 0, 'State variable awaitDrain is not correct.' ); + + if (chunk.length === 32 * 1024) { // first chunk + readable.push(Buffer.alloc(34 * 1024)); // above hwm + // We should check if awaitDrain counter is increased in the next + // tick, because awaitDrain is incremented after this method finished + process.nextTick(() => { + assert.strictEqual(readable._readableState.awaitDrain, 1, + 'Counter is not increased for awaitDrain'); + }); + } + cb(); }, 3) }); diff --git a/test/parallel/test-stream-readable-emittedReadable.js b/test/parallel/test-stream-readable-emittedReadable.js index 65b6b5b15a5..5b9affc59fb 100644 --- a/test/parallel/test-stream-readable-emittedReadable.js +++ b/test/parallel/test-stream-readable-emittedReadable.js @@ -10,30 +10,33 @@ const readable = new Readable({ // Initialized to false. assert.strictEqual(readable._readableState.emittedReadable, false); +const expected = [Buffer.from('foobar'), Buffer.from('quo'), null]; readable.on('readable', common.mustCall(() => { // emittedReadable should be true when the readable event is emitted assert.strictEqual(readable._readableState.emittedReadable, true); - readable.read(); + assert.deepStrictEqual(readable.read(), expected.shift()); // emittedReadable is reset to false during read() assert.strictEqual(readable._readableState.emittedReadable, false); -}, 4)); +}, 3)); // When the first readable listener is just attached, // emittedReadable should be false assert.strictEqual(readable._readableState.emittedReadable, false); -// Each one of these should trigger a readable event. +// These trigger a single 'readable', as things are batched up process.nextTick(common.mustCall(() => { readable.push('foo'); })); process.nextTick(common.mustCall(() => { readable.push('bar'); })); -process.nextTick(common.mustCall(() => { + +// these triggers two readable events +setImmediate(common.mustCall(() => { readable.push('quo'); -})); -process.nextTick(common.mustCall(() => { - readable.push(null); + process.nextTick(common.mustCall(() => { + readable.push(null); + })); })); const noRead = new Readable({ diff --git a/test/parallel/test-stream-readable-needReadable.js b/test/parallel/test-stream-readable-needReadable.js index be397dc5dc5..7058e123f07 100644 --- a/test/parallel/test-stream-readable-needReadable.js +++ b/test/parallel/test-stream-readable-needReadable.js @@ -38,7 +38,7 @@ asyncReadable.on('readable', common.mustCall(() => { // then we need to notify the reader on future changes. assert.strictEqual(asyncReadable._readableState.needReadable, true); } -}, 3)); +}, 2)); process.nextTick(common.mustCall(() => { asyncReadable.push('foooo'); @@ -46,8 +46,9 @@ process.nextTick(common.mustCall(() => { process.nextTick(common.mustCall(() => { asyncReadable.push('bar'); })); -process.nextTick(common.mustCall(() => { +setImmediate(common.mustCall(() => { asyncReadable.push(null); + assert.strictEqual(asyncReadable._readableState.needReadable, false); })); const flowing = new Readable({ @@ -84,13 +85,13 @@ slowProducer.on('readable', common.mustCall(() => { process.nextTick(common.mustCall(() => { slowProducer.push('foo'); -})); -process.nextTick(common.mustCall(() => { - slowProducer.push('foo'); -})); -process.nextTick(common.mustCall(() => { - slowProducer.push('foo'); -})); -process.nextTick(common.mustCall(() => { - slowProducer.push(null); + process.nextTick(common.mustCall(() => { + slowProducer.push('foo'); + process.nextTick(common.mustCall(() => { + slowProducer.push('foo'); + process.nextTick(common.mustCall(() => { + slowProducer.push(null); + })); + })); + })); })); diff --git a/test/parallel/test-stream-readable-object-multi-push-async.js b/test/parallel/test-stream-readable-object-multi-push-async.js new file mode 100644 index 00000000000..4babfd12a27 --- /dev/null +++ b/test/parallel/test-stream-readable-object-multi-push-async.js @@ -0,0 +1,183 @@ +'use strict'; + +const common = require('../common'); +const assert = require('assert'); +const { Readable } = require('stream'); + +const MAX = 42; +const BATCH = 10; + +{ + const readable = new Readable({ + objectMode: true, + read: common.mustCall(function() { + console.log('>> READ'); + fetchData((err, data) => { + if (err) { + this.destroy(err); + return; + } + + if (data.length === 0) { + console.log('pushing null'); + this.push(null); + return; + } + + console.log('pushing'); + data.forEach((d) => this.push(d)); + }); + }, Math.floor(MAX / BATCH) + 2) + }); + + let i = 0; + function fetchData(cb) { + if (i > MAX) { + setTimeout(cb, 10, null, []); + } else { + const array = []; + const max = i + BATCH; + for (; i < max; i++) { + array.push(i); + } + setTimeout(cb, 10, null, array); + } + } + + readable.on('readable', () => { + let data; + console.log('readable emitted'); + while (data = readable.read()) { + console.log(data); + } + }); + + readable.on('end', common.mustCall(() => { + assert.strictEqual(i, (Math.floor(MAX / BATCH) + 1) * BATCH); + })); +} + +{ + const readable = new Readable({ + objectMode: true, + read: common.mustCall(function() { + console.log('>> READ'); + fetchData((err, data) => { + if (err) { + this.destroy(err); + return; + } + + if (data.length === 0) { + console.log('pushing null'); + this.push(null); + return; + } + + console.log('pushing'); + data.forEach((d) => this.push(d)); + }); + }, Math.floor(MAX / BATCH) + 2) + }); + + let i = 0; + function fetchData(cb) { + if (i > MAX) { + setTimeout(cb, 10, null, []); + } else { + const array = []; + const max = i + BATCH; + for (; i < max; i++) { + array.push(i); + } + setTimeout(cb, 10, null, array); + } + } + + readable.on('data', (data) => { + console.log('data emitted', data); + }); + + readable.on('end', common.mustCall(() => { + assert.strictEqual(i, (Math.floor(MAX / BATCH) + 1) * BATCH); + })); +} + +{ + const readable = new Readable({ + objectMode: true, + read: common.mustCall(function() { + console.log('>> READ'); + fetchData((err, data) => { + if (err) { + this.destroy(err); + return; + } + + console.log('pushing'); + data.forEach((d) => this.push(d)); + + if (data[BATCH - 1] >= MAX) { + console.log('pushing null'); + this.push(null); + } + }); + }, Math.floor(MAX / BATCH) + 1) + }); + + let i = 0; + function fetchData(cb) { + const array = []; + const max = i + BATCH; + for (; i < max; i++) { + array.push(i); + } + setTimeout(cb, 10, null, array); + } + + readable.on('data', (data) => { + console.log('data emitted', data); + }); + + readable.on('end', common.mustCall(() => { + assert.strictEqual(i, (Math.floor(MAX / BATCH) + 1) * BATCH); + })); +} + +{ + const readable = new Readable({ + objectMode: true, + read: common.mustNotCall() + }); + + readable.on('data', common.mustNotCall()); + + readable.push(null); + + let nextTickPassed = false; + process.nextTick(() => { + nextTickPassed = true; + }); + + readable.on('end', common.mustCall(() => { + assert.strictEqual(nextTickPassed, false); + })); +} + +{ + const readable = new Readable({ + objectMode: true, + read: common.mustCall() + }); + + readable.on('data', (data) => { + console.log('data emitted', data); + }); + + readable.on('end', common.mustCall()); + + setImmediate(() => { + readable.push('aaa'); + readable.push(null); + }); +} diff --git a/test/parallel/test-stream-readable-reading-readingMore.js b/test/parallel/test-stream-readable-reading-readingMore.js index e31d2dd921c..0af2eeb71f2 100644 --- a/test/parallel/test-stream-readable-reading-readingMore.js +++ b/test/parallel/test-stream-readable-reading-readingMore.js @@ -37,7 +37,8 @@ readable.on('readable', common.mustCall(() => { // if the stream has ended, we shouldn't be reading assert.strictEqual(state.ended, !state.reading); - if (readable.read() === null) // reached end of stream + const data = readable.read(); + if (data === null) // reached end of stream process.nextTick(common.mustCall(onStreamEnd, 1)); }, 2)); diff --git a/test/parallel/test-stream2-transform.js b/test/parallel/test-stream2-transform.js index d0859265428..68c25141aa2 100644 --- a/test/parallel/test-stream2-transform.js +++ b/test/parallel/test-stream2-transform.js @@ -306,25 +306,26 @@ const Transform = require('_stream_transform'); pt.write(Buffer.from('foog')); pt.write(Buffer.from('bark')); - assert.strictEqual(emits, 1); + assert.strictEqual(emits, 0); assert.strictEqual(pt.read(5).toString(), 'foogb'); assert.strictEqual(String(pt.read(5)), 'null'); + assert.strictEqual(emits, 0); pt.write(Buffer.from('bazy')); pt.write(Buffer.from('kuel')); - assert.strictEqual(emits, 2); + assert.strictEqual(emits, 0); assert.strictEqual(pt.read(5).toString(), 'arkba'); assert.strictEqual(pt.read(5).toString(), 'zykue'); assert.strictEqual(pt.read(5), null); pt.end(); - assert.strictEqual(emits, 3); + assert.strictEqual(emits, 1); assert.strictEqual(pt.read(5).toString(), 'l'); assert.strictEqual(pt.read(5), null); - assert.strictEqual(emits, 3); + assert.strictEqual(emits, 1); } { @@ -338,7 +339,7 @@ const Transform = require('_stream_transform'); pt.write(Buffer.from('foog')); pt.write(Buffer.from('bark')); - assert.strictEqual(emits, 1); + assert.strictEqual(emits, 0); assert.strictEqual(pt.read(5).toString(), 'foogb'); assert.strictEqual(pt.read(5), null); @@ -352,7 +353,7 @@ const Transform = require('_stream_transform'); pt.once('readable', common.mustCall(function() { assert.strictEqual(pt.read(5).toString(), 'l'); assert.strictEqual(pt.read(5), null); - assert.strictEqual(emits, 4); + assert.strictEqual(emits, 3); })); pt.end(); })); diff --git a/test/parallel/test-url-format-invalid-input.js b/test/parallel/test-url-format-invalid-input.js index a94546aaf27..4f0f1a11d70 100644 --- a/test/parallel/test-url-format-invalid-input.js +++ b/test/parallel/test-url-format-invalid-input.js @@ -14,13 +14,14 @@ const throwsObjsAndReportTypes = new Map([ ]); for (const [urlObject, type] of throwsObjsAndReportTypes) { - const error = common.expectsError({ + common.expectsError(function() { + url.format(urlObject); + }, { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, message: 'The "urlObject" argument must be one of type Object or string. ' + `Received type ${type}` }); - assert.throws(function() { url.format(urlObject); }, error); } assert.strictEqual(url.format(''), ''); assert.strictEqual(url.format({}), ''); diff --git a/test/parallel/test-url-parse-invalid-input.js b/test/parallel/test-url-parse-invalid-input.js index acc676ebb38..a065acc58d3 100644 --- a/test/parallel/test-url-parse-invalid-input.js +++ b/test/parallel/test-url-parse-invalid-input.js @@ -16,12 +16,13 @@ const url = require('url'); [() => {}, 'function'], [Symbol('foo'), 'symbol'] ].forEach(([val, type]) => { - const error = common.expectsError({ + common.expectsError(() => { + url.parse(val); + }, { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, message: `The "url" argument must be of type string. Received type ${type}` }); - assert.throws(() => { url.parse(val); }, error); }); const engineSpecificMalformedUrlError = diff --git a/test/parallel/test-util-inherits.js b/test/parallel/test-util-inherits.js index 9c610e38004..afbd504bebb 100644 --- a/test/parallel/test-util-inherits.js +++ b/test/parallel/test-util-inherits.js @@ -3,11 +3,6 @@ const common = require('../common'); const assert = require('assert'); const inherits = require('util').inherits; -const errCheck = common.expectsError({ - code: 'ERR_INVALID_ARG_TYPE', - type: TypeError, - message: 'The "superCtor" argument must be of type Function' -}); // super constructor function A() { @@ -86,16 +81,20 @@ common.expectsError(function() { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, message: 'The "superCtor.prototype" property must be of type Function' -} -); -assert.throws(function() { +}); + +common.expectsError(function() { inherits(A, null); -}, errCheck); +}, { + code: 'ERR_INVALID_ARG_TYPE', + type: TypeError, + message: 'The "superCtor" argument must be of type Function' +}); + common.expectsError(function() { inherits(null, A); }, { code: 'ERR_INVALID_ARG_TYPE', type: TypeError, message: 'The "ctor" argument must be of type Function' -} -); +}); diff --git a/test/parallel/test-zlib.js b/test/parallel/test-zlib.js index b2201fca4c9..1f6965d1247 100644 --- a/test/parallel/test-zlib.js +++ b/test/parallel/test-zlib.js @@ -157,7 +157,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));