diff --git a/.eslintrc.js b/.eslintrc.js
index 55b61cea63be6c..32c85741802f39 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -8,6 +8,10 @@ const path = require('path');
const NodePlugin = require('./tools/node_modules/eslint-plugin-node-core');
NodePlugin.RULES_DIR = path.resolve(__dirname, 'tools', 'eslint-rules');
+// The Module._findPath() monkeypatching is to make it so that ESLint will work
+// if invoked by a globally-installed ESLint or ESLint installed elsewhere
+// rather than the one we ship. This makes it possible for IDEs to lint files
+// with our rules while people edit them.
const ModuleFindPath = Module._findPath;
const hacks = [
'eslint-plugin-node-core',
@@ -236,7 +240,7 @@ module.exports = {
{
selector: "CallExpression[callee.property.name='strictEqual'][arguments.0.type='Literal']:not([arguments.1.type='Literal']):not([arguments.1.type='ObjectExpression']):not([arguments.1.type='ArrayExpression']):not([arguments.1.type='UnaryExpression'])",
message: 'The first argument should be the `actual`, not the `expected` value.',
- }
+ },
],
/* eslint-enable max-len */
'no-return-await': 'error',
diff --git a/.github/SUPPORT.md b/.github/SUPPORT.md
new file mode 100644
index 00000000000000..1a086bd2cc59a7
--- /dev/null
+++ b/.github/SUPPORT.md
@@ -0,0 +1,26 @@
+# Support
+
+Node.js contributors have limited availability to address general support
+questions. Please make sure you are using a [currently-supported version of
+Node.js](https://github.com/nodejs/Release#release-schedule).
+
+When looking for support, please first search for your question in these venues:
+
+* [Node.js Website](https://nodejs.org/en/), especially the
+ [API docs](https://nodejs.org/api/)
+* [Node.js Help](https://github.com/nodejs/help)
+* [Open or closed issues in the Node.js GitHub organization](https://github.com/issues?utf8=%E2%9C%93&q=sort%3Aupdated-desc+org%3Anodejs+is%3Aissue)
+
+If you didn't find an answer in the resources above, try these unofficial
+resources:
+
+* [Questions tagged 'node.js' on Stack Overflow](https://stackoverflow.com/questions/tagged/node.js)
+* [#node.js channel on chat.freenode.net](https://webchat.freenode.net?channels=node.js&uio=d4)
+* [Node.js Slack Community](https://node-js.slack.com/)
+ * To register: [nodeslackers.com](http://www.nodeslackers.com/)
+
+GitHub issues are for tracking enhancements and bugs, not general support.
+
+The open source license grants you the freedom to use Node.js. It does not
+guarantee commitments of other people's time. Please be respectful and manage
+your expectations.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b7bf473720886a..6d36375decdbd3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,7 +29,8 @@ release.
-12.3.1
+12.4.0
+12.3.1 12.3.0 12.2.0 12.1.0
diff --git a/README.md b/README.md
index 0ab0dfbd6d65cf..185aac7f455430 100644
--- a/README.md
+++ b/README.md
@@ -28,37 +28,16 @@ The Node.js project uses an [open governance model](./GOVERNANCE.md). The
* [Verifying Binaries](#verifying-binaries)
* [Building Node.js](#building-nodejs)
* [Security](#security)
+* [Contributing to Node.js](#contributing-to-nodejs)
* [Current Project Team Members](#current-project-team-members)
* [TSC (Technical Steering Committee)](#tsc-technical-steering-committee)
* [Collaborators](#collaborators)
* [Release Keys](#release-keys)
-* [Contributing to Node.js](#contributing-to-nodejs)
## Support
-Node.js contributors have limited availability to address general support
-questions. Please make sure you are using a [currently-supported version of
-Node.js](https://github.com/nodejs/Release#release-schedule).
-
-When looking for support, please first search for your question in these venues:
-
-* [Node.js Website][]
-* [Node.js Help][]
-* [Open or closed issues in the Node.js GitHub organization](https://github.com/issues?utf8=%E2%9C%93&q=sort%3Aupdated-desc+org%3Anodejs+is%3Aissue)
-
-If you didn't find an answer in the resources above, try these unofficial
-resources:
-
-* [Questions tagged 'node.js' on StackOverflow][]
-* [#node.js channel on chat.freenode.net][]
-* [Node.js Slack Community](https://node-js.slack.com/)
- * To register: [nodeslackers.com](http://www.nodeslackers.com/)
-
-GitHub issues are for tracking enhancements and bugs, not general support.
-
-The open source license grants you the freedom to use Node.js. It does not
-guarantee commitments of other people's time. Please be respectful and manage
-your expectations.
+Looking for help? Check out the
+[instructions for getting support](.github/SUPPORT.md).
## Release Types
@@ -160,6 +139,12 @@ source and a list of supported platforms.
For information on reporting security vulnerabilities in Node.js, see
[SECURITY.md](./SECURITY.md).
+## Contributing to Node.js
+
+* [Contributing to the project][]
+* [Working Groups][]
+* [Strategic Initiatives][]
+
## Current Project Team Members
For information about the governance of the Node.js project, see
@@ -400,7 +385,7 @@ For information about the governance of the Node.js project, see
* [Qard](https://github.com/Qard) -
**Stephen Belanger** <admin@stephenbelanger.com> (he/him)
* [refack](https://github.com/refack) -
-**Refael Ackermann** <refack@gmail.com> (he/him)
+**Refael Ackermann (רפאל פלחי)** <refack@gmail.com> (he/him/הוא/אתה)
* [richardlau](https://github.com/richardlau) -
**Richard Lau** <riclau@uk.ibm.com>
* [ronkorving](https://github.com/ronkorving) -
@@ -593,18 +578,8 @@ Other keys used to sign some previous releases:
* **Timothy J Fontaine** <tjfontaine@gmail.com>
`7937DFD2AB06298B2293C3187D33FF9D0246406D`
-## Contributing to Node.js
-
-* [Contributing to the project][]
-* [Working Groups][]
-* [Strategic Initiatives][]
-
[Code of Conduct]: https://github.com/nodejs/admin/blob/master/CODE_OF_CONDUCT.md
[Contributing to the project]: CONTRIBUTING.md
-[Node.js Help]: https://github.com/nodejs/help
[Node.js Foundation]: https://nodejs.org/en/foundation/
-[Node.js Website]: https://nodejs.org/en/
-[Questions tagged 'node.js' on StackOverflow]: https://stackoverflow.com/questions/tagged/node.js
[Working Groups]: https://github.com/nodejs/TSC/blob/master/WORKING_GROUPS.md
[Strategic Initiatives]: https://github.com/nodejs/TSC/blob/master/Strategic-Initiatives.md
-[#node.js channel on chat.freenode.net]: https://webchat.freenode.net?channels=node.js&uio=d4
diff --git a/deps/histogram/histogram.gyp b/deps/histogram/histogram.gyp
index bcfa198f9d37c1..e3f5fd7a46bb72 100644
--- a/deps/histogram/histogram.gyp
+++ b/deps/histogram/histogram.gyp
@@ -3,6 +3,10 @@
{
'target_name': 'histogram',
'type': 'static_library',
+ 'cflags': ['-fvisibility=hidden'],
+ 'xcode_settings': {
+ 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
+ },
'include_dirs': ['src'],
'direct_dependent_settings': {
'include_dirs': [ 'src' ]
diff --git a/doc/api/assert.md b/doc/api/assert.md
index 0a7d35f105e48e..22383a16b62d14 100644
--- a/doc/api/assert.md
+++ b/doc/api/assert.md
@@ -68,7 +68,7 @@ try {
} catch (err) {
assert(err instanceof assert.AssertionError);
assert.strictEqual(err.message, message);
- assert.strictEqual(err.name, 'AssertionError [ERR_ASSERTION]');
+ assert.strictEqual(err.name, 'AssertionError');
assert.strictEqual(err.actual, 1);
assert.strictEqual(err.expected, 2);
assert.strictEqual(err.code, 'ERR_ASSERTION');
diff --git a/doc/api/cli.md b/doc/api/cli.md
index 42950418282ef2..e6e507ddb6c5c5 100644
--- a/doc/api/cli.md
+++ b/doc/api/cli.md
@@ -148,13 +148,6 @@ the ability to import a directory that has an index file.
Please see [customizing esm specifier resolution][] for example usage.
-### `--experimental-json-modules`
-
-
-Enable experimental JSON support for the ES Module loader.
-
### `--experimental-modules`
+
+Enable experimental WebAssembly module support.
+
### `--force-fips`
+### `--heap-prof`
+
+
+> Stability: 1 - Experimental
+
+Starts the V8 heap profiler on start up, and writes the heap profile to disk
+before exit.
+
+If `--heap-prof-dir` is not specified, the generated profile will be placed
+in the current working directory.
+
+If `--heap-prof-name` is not specified, the generated profile will be
+named `Heap.${yyyymmdd}.${hhmmss}.${pid}.${tid}.${seq}.heapprofile`.
+
+```console
+$ node --heap-prof index.js
+$ ls *.heapprofile
+Heap.20190409.202950.15293.0.001.heapprofile
+```
+
+### `--heap-prof-dir`
+
+
+> Stability: 1 - Experimental
+
+Specify the directory where the heap profiles generated by `--heap-prof` will
+be placed.
+
+### `--heap-prof-interval`
+
+
+> Stability: 1 - Experimental
+
+Specify the average sampling interval in bytes for the heap profiles generated
+by `--heap-prof`. The default is 512 * 1024 bytes.
+
+### `--heap-prof-name`
+
+
+> Stability: 1 - Experimental
+
+Specify the file name of the heap profile generated by `--heap-prof`.
+
Generates a heap snapshot each time the process receives the specified signal.
`signal` must be a valid signal name. Disabled by default.
@@ -271,6 +322,17 @@ This flag exists to aid in experimentation with the internal implementation of
the Node.js http parser.
This flag is likely to become a no-op and removed at some point in the future.
+### `--http-server-default-timeout=milliseconds`
+
+
+Overrides the default value of `http`, `https` and `http2` server socket
+timeout. Setting the value to 0 disables server socket timeout. Unless
+provided, http server sockets timeout after 120s (2 minutes). Programmatic
+setting of the timeout takes precedence over the value set through this
+flag.
+
### `--icu-data-dir=file`
+Type: Runtime
+
The undocumented `net._setSimultaneousAccepts()` function was originally
intended for debugging and performance tuning when using the `child_process`
and `cluster` modules on Windows. The function is not generally useful and
diff --git a/doc/api/documentation.md b/doc/api/documentation.md
index 612b6f2dbf545b..c0733f266dd830 100644
--- a/doc/api/documentation.md
+++ b/doc/api/documentation.md
@@ -9,24 +9,17 @@ Node.js is a JavaScript runtime built on the [V8 JavaScript engine][].
## Contributing
-If errors are found in this documentation, please [submit an issue][]
-or see [the contributing guide][] for directions on how to submit a patch.
+Report errors in this documentation in [the issue tracker][]. See
+[the contributing guide][] for directions on how to submit pull requests.
-Every file is generated based on the corresponding `.md` file in the
-`doc/api/` folder in Node.js's source tree. The documentation is generated
-using the `tools/doc/generate.js` program. An HTML template is located at
-`doc/template.html`.
## Stability Index
-Throughout the documentation are indications of a section's
-stability. The Node.js API is still somewhat changing, and as it
-matures, certain parts are more reliable than others. Some are so
-proven, and so relied upon, that they are unlikely to ever change at
-all. Others are brand new and experimental, or known to be hazardous
-and being redesigned.
+Throughout the documentation are indications of a section's stability. Some APIs
+are so proven and so relied upon that they are unlikely to ever change at all.
+Others are brand new and experimental, or known to be hazardous.
The stability indices are as follows:
@@ -35,55 +28,38 @@ The stability indices are as follows:
-> Stability: 1 - Experimental. This feature is still under active development
-> and subject to non-backward compatible changes or removal in any future
-> version. Use of the feature is not recommended in production environments.
-> Experimental features are not subject to the Node.js Semantic Versioning
-> model.
+> Stability: 1 - Experimental. The feature is not subject to Semantic Versioning
+> rules. Non-backward compatible changes or removal may occur in any future
+> release. Use of the feature is not recommended in production environments.
> Stability: 2 - Stable. Compatibility with the npm ecosystem is a high
> priority.
-Use caution when making use of `Experimental` features, particularly
-within modules that are dependencies (or dependencies of
-dependencies) within a Node.js application. End users may not be aware that
-experimental features are being used, and may experience unexpected
-failures or behavior changes when API modifications occur. To help avoid such
-surprises, `Experimental` features may require a command-line flag to
-enable them, or may emit a process warning.
-By default, such warnings are printed to [`stderr`][] and may be handled by
-attaching a listener to the [`'warning'`][] event.
+Use caution when making use of Experimental features, particularly within
+modules. End users may not be aware that experimental features are being used.
+Bugs or behavior changes may surprise end users when Experimental API
+modifications occur. To avoid surprises, use of an Experimental feature may need
+a command-line flag. Experimental features may also emit a [warning][].
## JSON Output
-> Stability: 1 - Experimental
+Every `.html` document has a corresponding `.json` document. This is for IDEs
+and other utilities that consume the documentation.
-Every `.html` document has a corresponding `.json` document presenting
-the same information in a structured manner. This feature is
-experimental, and added for the benefit of IDEs and other utilities that
-wish to do programmatic things with the documentation.
+## System calls and man pages
-## Syscalls and man pages
+Node.js functions which wrap a system call will document that. The docs link
+to the corresponding man pages which describe how the system call works.
-System calls like open(2) and read(2) define the interface between user programs
-and the underlying operating system. Node.js functions
-which wrap a syscall,
-like [`fs.open()`][], will document that. The docs link to the corresponding man
-pages (short for manual pages) which describe how the syscalls work.
+Most Unix system calls have Windows analogues. Still, behavior differences may
+be unavoidable.
-Most Unix syscalls have Windows equivalents, but behavior may differ on Windows
-relative to Linux and macOS. For an example of the subtle ways in which it's
-sometimes impossible to replace Unix syscall semantics on Windows, see [Node.js
-issue 4760](https://github.com/nodejs/node/issues/4760).
-
-[`'warning'`]: process.html#process_event_warning
-[`fs.open()`]: fs.html#fs_fs_open_path_flags_mode_callback
-[`stderr`]: process.html#process_process_stderr
-[submit an issue]: https://github.com/nodejs/node/issues/new
[the contributing guide]: https://github.com/nodejs/node/blob/master/CONTRIBUTING.md
+[the issue tracker]: https://github.com/nodejs/node/issues/new
[V8 JavaScript engine]: https://v8.dev/
+[warning]: process.html#process_event_warning
diff --git a/doc/api/errors.md b/doc/api/errors.md
index 9420e07b16c871..ebbe215b6075f1 100644
--- a/doc/api/errors.md
+++ b/doc/api/errors.md
@@ -2349,7 +2349,7 @@ such as `process.stdout.on('data')`.
[`sign.sign()`]: crypto.html#crypto_sign_sign_privatekey_outputencoding
[`stream.pipe()`]: stream.html#stream_readable_pipe_destination_options
[`stream.push()`]: stream.html#stream_readable_push_chunk_encoding
-[`stream.unshift()`]: stream.html#stream_readable_unshift_chunk
+[`stream.unshift()`]: stream.html#stream_readable_unshift_chunk_encoding
[`stream.write()`]: stream.html#stream_writable_write_chunk_encoding_callback
[`subprocess.kill()`]: child_process.html#child_process_subprocess_kill_signal
[`subprocess.send()`]: child_process.html#child_process_subprocess_send_message_sendhandle_options_callback
diff --git a/doc/api/esm.md b/doc/api/esm.md
index 646e7d5e9966ec..1ea41e84c1d53d 100644
--- a/doc/api/esm.md
+++ b/doc/api/esm.md
@@ -409,18 +409,11 @@ fs.readFileSync = () => Buffer.from('Hello, ESM');
fs.readFileSync === readFileSync;
```
-## Experimental JSON Modules
+## JSON Modules
-**Note: This API is still being designed and is subject to change.**
+JSON modules follow the [WHATWG JSON modules specification][].
-Currently importing JSON modules are only supported in the `commonjs` mode
-and are loaded using the CJS loader. [WHATWG JSON modules][] are currently
-being standardized, and are experimentally supported by including the
-additional flag `--experimental-json-modules` when running Node.js.
-
-When the `--experimental-json-modules` flag is included both the
-`commonjs` and `module` mode will use the new experimental JSON
-loader. The imported JSON only exposes a `default`, there is no
+The imported JSON only exposes a `default`. There is no
support for named exports. A cache entry is created in the CommonJS
cache, to avoid duplication. The same object will be returned in
CommonJS if the JSON module has already been imported from the
@@ -433,14 +426,6 @@ Assuming an `index.mjs` with
import packageConfig from './package.json';
```
-The `--experimental-json-modules` flag is needed for the module
-to work.
-
-```bash
-node --experimental-modules index.mjs # fails
-node --experimental-modules --experimental-json-modules index.mjs # works
-```
-
## Experimental Wasm Modules
Importing Web Assembly modules is supported under the
@@ -763,7 +748,7 @@ success!
[CommonJS]: modules.html
[ECMAScript-modules implementation]: https://github.com/nodejs/modules/blob/master/doc/plan-for-new-modules-implementation.md
[Node.js EP for ES Modules]: https://github.com/nodejs/node-eps/blob/master/002-es-modules.md
-[WHATWG JSON modules]: https://github.com/whatwg/html/issues/4315
+[WHATWG JSON modules specification]: https://html.spec.whatwg.org/#creating-a-json-module-script
[ES Module Integration Proposal for Web Assembly]: https://github.com/webassembly/esm-integration
[dynamic instantiate hook]: #esm_dynamic_instantiate_hook
[the official standard format]: https://tc39.github.io/ecma262/#sec-modules
diff --git a/doc/api/fs.md b/doc/api/fs.md
index 3b3c6efd58243f..d2506d28e33cce 100644
--- a/doc/api/fs.md
+++ b/doc/api/fs.md
@@ -2898,7 +2898,8 @@ changes:
Asynchronously rename file at `oldPath` to the pathname provided
as `newPath`. In the case that `newPath` already exists, it will
-be overwritten. No arguments other than a possible exception are
+be overwritten. If there is a directory at `newPath`, an error will
+be raised instead. No arguments other than a possible exception are
given to the completion callback.
See also: rename(2).
@@ -3733,9 +3734,14 @@ added: v10.0.0
A `FileHandle` object is a wrapper for a numeric file descriptor.
Instances of `FileHandle` are distinct from numeric file descriptors
-in that, if the `FileHandle` is not explicitly closed using the
-`filehandle.close()` method, they will automatically close the file descriptor
+in that they provide an object oriented API for working with files.
+
+If a `FileHandle` is not closed using the
+`filehandle.close()` method, it might automatically close the file descriptor
and will emit a process warning, thereby helping to prevent memory leaks.
+Please do not rely on this behavior in your code because it is unreliable and
+your file may not be closed. Instead, always explicitly close `FileHandle`s.
+Node.js may change this behavior in the future.
Instances of the `FileHandle` object are created internally by the
`fsPromises.open()` method.
diff --git a/doc/api/http.md b/doc/api/http.md
index ccd5e4b0bd4b30..da0de7c1e68603 100644
--- a/doc/api/http.md
+++ b/doc/api/http.md
@@ -1030,6 +1030,9 @@ By default, the Server's timeout value is 2 minutes, and sockets are
destroyed automatically if they time out. However, if a callback is assigned
to the Server's `'timeout'` event, timeouts must be handled explicitly.
+To change the default timeout use the [`--http-server-default-timeout`][]
+flag.
+
### server.timeout
It is convenient to organize programs and libraries into self-contained
-directories, and then provide a single entry point to that library.
+directories, and then provide a single entry point to those directories.
There are three ways in which a folder may be passed to `require()` as
an argument.
diff --git a/doc/api/n-api.md b/doc/api/n-api.md
index a39f62aa74cc2b..f648ab1d18f752 100644
--- a/doc/api/n-api.md
+++ b/doc/api/n-api.md
@@ -7,7 +7,7 @@
N-API (pronounced N as in the letter, followed by API)
is an API for building native Addons. It is independent from
-the underlying JavaScript runtime (ex V8) and is maintained as part of
+the underlying JavaScript runtime (for example, V8) and is maintained as part of
Node.js itself. This API will be Application Binary Interface (ABI) stable
across versions of Node.js. It is intended to insulate Addons from
changes in the underlying JavaScript engine and allow modules
@@ -148,7 +148,7 @@ available to the module code.
| | 1 | 2 | 3 | 4 |
|:-----:|:-------:|:--------:|:--------:|:--------:|
| v6.x | | | v6.14.2* | |
-| v8.x | v8.0.0* | v8.10.0* | v8.11.2 | |
+| v8.x | v8.0.0* | v8.10.0* | v8.11.2 | v8.16.0 |
| v9.x | v9.0.0* | v9.3.0* | v9.11.0* | |
| v10.x | | | v10.0.0 | |
| v11.x | | | v11.0.0 | v11.8.0 |
@@ -222,6 +222,10 @@ consumed by the various APIs. These APIs should be treated as opaque,
introspectable only with other N-API calls.
### napi_status
+
Integral status code indicating the success or failure of a N-API call.
Currently, the following status codes are supported.
```C
@@ -251,6 +255,10 @@ If additional information is required upon an API returning a failed status,
it can be obtained by calling `napi_get_last_error_info`.
### napi_extended_error_info
+
```C
typedef struct {
const char* error_message;
@@ -283,12 +291,20 @@ not allowed.
This is an opaque pointer that is used to represent a JavaScript value.
### napi_threadsafe_function
+
This is an opaque pointer that represents a JavaScript function which can be
called asynchronously from multiple threads via
`napi_call_threadsafe_function()`.
### napi_threadsafe_function_release_mode
+
A value to be given to `napi_release_threadsafe_function()` to indicate whether
the thread-safe function is to be closed immediately (`napi_tsfn_abort`) or
@@ -302,6 +318,10 @@ typedef enum {
```
### napi_threadsafe_function_call_mode
+
A value to be given to `napi_call_threadsafe_function()` to indicate whether
the call should block whenever the queue associated with the thread-safe
@@ -333,10 +353,18 @@ longer referenced from the current stack frame.
For more details, review the [Object Lifetime Management][].
#### napi_escapable_handle_scope
+
Escapable handle scopes are a special type of handle scope to return values
created within a particular handle scope to a parent scope.
#### napi_ref
+
This is the abstraction to use to reference a `napi_value`. This allows for
users to manage the lifetimes of JavaScript values, including defining their
minimum lifetimes explicitly.
@@ -345,11 +373,19 @@ For more details, review the [Object Lifetime Management][].
### N-API Callback types
#### napi_callback_info
+
Opaque datatype that is passed to a callback function. It can be used for
getting additional information about the context in which the callback was
invoked.
#### napi_callback
+
Function pointer type for user-provided native functions which are to be
exposed to JavaScript via N-API. Callback functions should satisfy the
following signature:
@@ -358,6 +394,10 @@ typedef napi_value (*napi_callback)(napi_env, napi_callback_info);
```
#### napi_finalize
+
Function pointer type for add-on provided functions that allow the user to be
notified when externally-owned data is ready to be cleaned up because the
object with which it was associated with, has been garbage-collected. The user
@@ -372,6 +412,10 @@ typedef void (*napi_finalize)(napi_env env,
```
#### napi_async_execute_callback
+
Function pointer used with functions that support asynchronous
operations. Callback functions must satisfy the following signature:
@@ -385,6 +429,10 @@ JavaScript objects. Most often, any code that needs to make N-API
calls should be made in `napi_async_complete_callback` instead.
#### napi_async_complete_callback
+
Function pointer used with functions that support asynchronous
operations. Callback functions must satisfy the following signature:
@@ -395,6 +443,10 @@ typedef void (*napi_async_complete_callback)(napi_env env,
```
#### napi_threadsafe_function_call_js
+
Function pointer used with asynchronous thread-safe function calls. The callback
will be called on the main thread. Its purpose is to use a data item arriving
@@ -460,6 +512,10 @@ In order to retrieve this information [`napi_get_last_error_info`][]
is provided which returns a `napi_extended_error_info` structure.
The format of the `napi_extended_error_info` structure is as follows:
+
```C
typedef struct napi_extended_error_info {
const char* error_message;
diff --git a/doc/api/stream.md b/doc/api/stream.md
index 8b525b953ba2bb..46f4226039c2df 100644
--- a/doc/api/stream.md
+++ b/doc/api/stream.md
@@ -1195,7 +1195,7 @@ setTimeout(() => {
}, 1000);
```
-##### readable.unshift(chunk)
+##### readable.unshift(chunk[, encoding])
```js
{
@@ -149,7 +160,9 @@ to get swapped out by the operating system.
heap_size_limit: 1535115264,
malloced_memory: 16384,
peak_malloced_memory: 1127496,
- does_zap_garbage: 0
+ does_zap_garbage: 0,
+ number_of_native_contexts: 1,
+ number_of_detached_contexts: 0
}
```
diff --git a/doc/changelogs/CHANGELOG_V12.md b/doc/changelogs/CHANGELOG_V12.md
index 9eb0f5e401fcaa..7bd3ffd62fc391 100644
--- a/doc/changelogs/CHANGELOG_V12.md
+++ b/doc/changelogs/CHANGELOG_V12.md
@@ -9,6 +9,7 @@
+12.4.0 12.3.1 12.3.0 12.2.0
@@ -32,6 +33,142 @@
* [io.js](CHANGELOG_IOJS.md)
* [Archive](CHANGELOG_ARCHIVE.md)
+
+## 2019-06-04, Version 12.4.0 (Current), @targos
+
+### Notable changes
+
+* **doc**:
+ * The JSON variant of the API documentation is no longer experimental (Rich Trott) [#27842](https://github.com/nodejs/node/pull/27842).
+* **esm**:
+ * JSON module support is always enabled under `--experimental-modules`. The
+ `--experimental-json-modules` flag has been removed (Myles Borins) [#27752](https://github.com/nodejs/node/pull/27752).
+* **http,http2**:
+ * A new flag has been added for overriding the default HTTP server socket
+ timeout (which is two minutes). Pass `--http-server-default-timeout=milliseconds`
+ or `--http-server-default-timeout=0` to respectively change or disable the timeout.
+ Starting with Node.js 13.0.0, the timeout will be disabled by default (Ali Ijaz Sheikh) [#27704](https://github.com/nodejs/node/pull/27704).
+* **inspector**:
+ * Added an experimental `--heap-prof` flag to start the V8 heap profiler
+ on startup and write the heap profile to disk before exit (Joyee Cheung) [#27596](https://github.com/nodejs/node/pull/27596).
+* **stream**:
+ * The `readable.unshift()` method now correctly converts strings to buffers.
+ Additionally, a new optional argument is accepted to specify the string's
+ encoding, such as `'utf8'` or `'ascii'` (Marcos Casagrande) [#27194](https://github.com/nodejs/node/pull/27194).
+* **v8**:
+ * The object returned by `v8.getHeapStatistics()` has two new properties:
+ `number_of_native_contexts` and `number_of_detached_contexts` (Yuriy Vasiyarov) [#27933](https://github.com/nodejs/node/pull/27933).
+
+### Commits
+
+* [[`5bbc6d79c3`](https://github.com/nodejs/node/commit/5bbc6d79c3)] - **assert**: remove unreachable code (Rich Trott) [#27840](https://github.com/nodejs/node/pull/27840)
+* [[`530e63a4eb`](https://github.com/nodejs/node/commit/530e63a4eb)] - **assert**: remove unreachable code (Rich Trott) [#27786](https://github.com/nodejs/node/pull/27786)
+* [[`9b08c458be`](https://github.com/nodejs/node/commit/9b08c458be)] - **build,aix**: link with `noerrmsg` to eliminate warnings (Refael Ackermann) [#27773](https://github.com/nodejs/node/pull/27773)
+* [[`08b0ca9645`](https://github.com/nodejs/node/commit/08b0ca9645)] - **build,win**: create junction instead of symlink to `out\\%config%` (Refael Ackermann) [#27736](https://github.com/nodejs/node/pull/27736)
+* [[`ea2d550507`](https://github.com/nodejs/node/commit/ea2d550507)] - **child_process**: move exports to bottom for consistent code style (himself65) [#27845](https://github.com/nodejs/node/pull/27845)
+* [[`a9f95572c3`](https://github.com/nodejs/node/commit/a9f95572c3)] - **child_process**: remove extra shallow copy (zero1five) [#27801](https://github.com/nodejs/node/pull/27801)
+* [[`449ee8dd42`](https://github.com/nodejs/node/commit/449ee8dd42)] - **console**: fix table() output (Brian White) [#27917](https://github.com/nodejs/node/pull/27917)
+* [[`9220a68a76`](https://github.com/nodejs/node/commit/9220a68a76)] - **crypto**: fix KeyObject handle type error message (Alexander Avakov) [#27904](https://github.com/nodejs/node/pull/27904)
+* [[`3b6424fa29`](https://github.com/nodejs/node/commit/3b6424fa29)] - **deps**: histogram: unexport symbols (Ben Noordhuis) [#27779](https://github.com/nodejs/node/pull/27779)
+* [[`ef25ac5223`](https://github.com/nodejs/node/commit/ef25ac5223)] - **doc**: clarify wording in modules.md (Alex Temny) [#27853](https://github.com/nodejs/node/pull/27853)
+* [[`c683cd99d7`](https://github.com/nodejs/node/commit/c683cd99d7)] - **doc**: improve explanation for directory with fs.rename() (Rich Trott) [#27963](https://github.com/nodejs/node/pull/27963)
+* [[`70b485478c`](https://github.com/nodejs/node/commit/70b485478c)] - **doc**: fix the wrong name of AssertionError (Kyle Zhang) [#27982](https://github.com/nodejs/node/pull/27982)
+* [[`11c3ddb4cb`](https://github.com/nodejs/node/commit/11c3ddb4cb)] - **doc**: simplify system call material in doc overview (Rich Trott) [#27966](https://github.com/nodejs/node/pull/27966)
+* [[`c56640138a`](https://github.com/nodejs/node/commit/c56640138a)] - **doc**: warn about relying on fs gc close behavior (Benjamin Gruenbaum) [#27972](https://github.com/nodejs/node/pull/27972)
+* [[`bab9f5a891`](https://github.com/nodejs/node/commit/bab9f5a891)] - **doc**: add information to revoked deprecations (cjihrig) [#27952](https://github.com/nodejs/node/pull/27952)
+* [[`f4fc75d245`](https://github.com/nodejs/node/commit/f4fc75d245)] - **doc**: add missing status to DEP0121 (cjihrig) [#27950](https://github.com/nodejs/node/pull/27950)
+* [[`77ff597faa`](https://github.com/nodejs/node/commit/77ff597faa)] - **doc**: add missing --experimental-wasm-modules docs (cjihrig) [#27948](https://github.com/nodejs/node/pull/27948)
+* [[`6ca4f03ccf`](https://github.com/nodejs/node/commit/6ca4f03ccf)] - **doc**: revise additional Experimental status text (Rich Trott) [#27931](https://github.com/nodejs/node/pull/27931)
+* [[`a1788de0a4`](https://github.com/nodejs/node/commit/a1788de0a4)] - **doc**: adds link to nightly code coverage report (Tariq Ramlall) [#27922](https://github.com/nodejs/node/pull/27922)
+* [[`b7cd0de145`](https://github.com/nodejs/node/commit/b7cd0de145)] - **doc**: fix typo in pipe from async iterator example (Luigi Pinca) [#27870](https://github.com/nodejs/node/pull/27870)
+* [[`f621b8f178`](https://github.com/nodejs/node/commit/f621b8f178)] - **doc**: reword Experimental stability index (Rich Trott) [#27879](https://github.com/nodejs/node/pull/27879)
+* [[`7a7fc4e7e6`](https://github.com/nodejs/node/commit/7a7fc4e7e6)] - **doc**: update n-api support matrix (teams2ua) [#27567](https://github.com/nodejs/node/pull/27567)
+* [[`9d9b32eff5`](https://github.com/nodejs/node/commit/9d9b32eff5)] - **doc**: fix for OutgoingMessage.prototype.\_headers/\_headerNames (Daniel Nalborczyk) [#27574](https://github.com/nodejs/node/pull/27574)
+* [[`263e53317b`](https://github.com/nodejs/node/commit/263e53317b)] - **doc**: reposition "How to Contribute" README section (Anish Asrani) [#27811](https://github.com/nodejs/node/pull/27811)
+* [[`85f505c292`](https://github.com/nodejs/node/commit/85f505c292)] - **doc**: add version info for types (Michael Dawson) [#27754](https://github.com/nodejs/node/pull/27754)
+* [[`e3bb2aef60`](https://github.com/nodejs/node/commit/e3bb2aef60)] - **doc**: remove experimental status for JSON documentation (Rich Trott) [#27842](https://github.com/nodejs/node/pull/27842)
+* [[`6981565c20`](https://github.com/nodejs/node/commit/6981565c20)] - **doc**: edit stability index overview (Rich Trott) [#27831](https://github.com/nodejs/node/pull/27831)
+* [[`1a8e67cc1f`](https://github.com/nodejs/node/commit/1a8e67cc1f)] - **doc**: simplify contributing documentation (Rich Trott) [#27785](https://github.com/nodejs/node/pull/27785)
+* [[`041b2220be`](https://github.com/nodejs/node/commit/041b2220be)] - **doc,n-api**: fix typo in N-API introduction (Richard Lau) [#27833](https://github.com/nodejs/node/pull/27833)
+* [[`6cd64c8279`](https://github.com/nodejs/node/commit/6cd64c8279)] - **doc,test**: clarify that Http2Stream is destroyed after data is read (Alba Mendez) [#27891](https://github.com/nodejs/node/pull/27891)
+* [[`cc69d5af8e`](https://github.com/nodejs/node/commit/cc69d5af8e)] - **doc,tools**: get altDocs versions from CHANGELOG.md (Richard Lau) [#27661](https://github.com/nodejs/node/pull/27661)
+* [[`e72d4aa522`](https://github.com/nodejs/node/commit/e72d4aa522)] - **errors**: create internal connResetException (Rich Trott) [#27953](https://github.com/nodejs/node/pull/27953)
+* [[`be1166fd01`](https://github.com/nodejs/node/commit/be1166fd01)] - **esm**: refactor createDynamicModule() (cjihrig) [#27809](https://github.com/nodejs/node/pull/27809)
+* [[`e66648e887`](https://github.com/nodejs/node/commit/e66648e887)] - **(SEMVER-MINOR)** **esm**: remove experimental status from JSON modules (Myles Borins) [#27752](https://github.com/nodejs/node/pull/27752)
+* [[`d948656635`](https://github.com/nodejs/node/commit/d948656635)] - **http**: fix deferToConnect comments (Robert Nagy) [#27876](https://github.com/nodejs/node/pull/27876)
+* [[`24eaeed393`](https://github.com/nodejs/node/commit/24eaeed393)] - **http**: fix socketOnWrap edge cases (Anatoli Papirovski) [#27968](https://github.com/nodejs/node/pull/27968)
+* [[`8b38dfbf39`](https://github.com/nodejs/node/commit/8b38dfbf39)] - **http**: call write callback even if there is no message body (Luigi Pinca) [#27777](https://github.com/nodejs/node/pull/27777)
+* [[`588fd0c20d`](https://github.com/nodejs/node/commit/588fd0c20d)] - **(SEMVER-MINOR)** **http, http2**: flag for overriding server timeout (Ali Ijaz Sheikh) [#27704](https://github.com/nodejs/node/pull/27704)
+* [[`799aeca134`](https://github.com/nodejs/node/commit/799aeca134)] - **http2**: respect inspect() depth (cjihrig) [#27983](https://github.com/nodejs/node/pull/27983)
+* [[`83aaef87d0`](https://github.com/nodejs/node/commit/83aaef87d0)] - **http2**: fix tracking received data for maxSessionMemory (Anna Henningsen) [#27914](https://github.com/nodejs/node/pull/27914)
+* [[`8c35198499`](https://github.com/nodejs/node/commit/8c35198499)] - **http2**: support net.Server options (Luigi Pinca) [#27782](https://github.com/nodejs/node/pull/27782)
+* [[`23119cacf8`](https://github.com/nodejs/node/commit/23119cacf8)] - **inspector**: supported NodeRuntime domain in worker (Aleksei Koziatinskii) [#27706](https://github.com/nodejs/node/pull/27706)
+* [[`89483be254`](https://github.com/nodejs/node/commit/89483be254)] - **inspector**: more conservative minimum stack size (Ben Noordhuis) [#27855](https://github.com/nodejs/node/pull/27855)
+* [[`512ab1fddf`](https://github.com/nodejs/node/commit/512ab1fddf)] - **inspector**: removing checking of non existent field in lib/inspector.js (Keroosha) [#27919](https://github.com/nodejs/node/pull/27919)
+* [[`d99e70381e`](https://github.com/nodejs/node/commit/d99e70381e)] - **SEMVER-MINOR** **inspector**: implement --heap-prof (Joyee Cheung) [#27596](https://github.com/nodejs/node/pull/27596)
+* [[`25eb05a97a`](https://github.com/nodejs/node/commit/25eb05a97a)] - **lib**: removed unnecessary fs.realpath `options` arg check + tests (Alex Pry) [#27909](https://github.com/nodejs/node/pull/27909)
+* [[`9b90385825`](https://github.com/nodejs/node/commit/9b90385825)] - ***Revert*** "**lib**: print to stdout/stderr directly instead of using console" (Richard Lau) [#27823](https://github.com/nodejs/node/pull/27823)
+* [[`18650579e8`](https://github.com/nodejs/node/commit/18650579e8)] - **meta**: correct personal info (Refael Ackermann (רפאל פלחי)) [#27940](https://github.com/nodejs/node/pull/27940)
+* [[`d982f0b7e2`](https://github.com/nodejs/node/commit/d982f0b7e2)] - **meta**: create github support file (Gus Caplan) [#27926](https://github.com/nodejs/node/pull/27926)
+* [[`2b7ad122b2`](https://github.com/nodejs/node/commit/2b7ad122b2)] - **n-api**: DRY napi\_coerce\_to\_x() API methods (Ben Noordhuis) [#27796](https://github.com/nodejs/node/pull/27796)
+* [[`1da5acbf91`](https://github.com/nodejs/node/commit/1da5acbf91)] - **os**: assume UTF-8 for hostname (Anna Henningsen) [#27849](https://github.com/nodejs/node/pull/27849)
+* [[`d406785814`](https://github.com/nodejs/node/commit/d406785814)] - **src**: unimplement deprecated v8-platform methods (Michaël Zasso) [#27872](https://github.com/nodejs/node/pull/27872)
+* [[`33236b7c54`](https://github.com/nodejs/node/commit/33236b7c54)] - **(SEMVER-MINOR)** **src**: export number\_of\_native\_contexts and number\_of\_detached\_contexts (Yuriy Vasiyarov) [#27933](https://github.com/nodejs/node/pull/27933)
+* [[`1a179e1736`](https://github.com/nodejs/node/commit/1a179e1736)] - **src**: use ArrayBufferViewContents more frequently (Anna Henningsen) [#27920](https://github.com/nodejs/node/pull/27920)
+* [[`b9cc4072e6`](https://github.com/nodejs/node/commit/b9cc4072e6)] - **src**: make UNREACHABLE variadic (Refael Ackermann) [#27877](https://github.com/nodejs/node/pull/27877)
+* [[`44846aebd2`](https://github.com/nodejs/node/commit/44846aebd2)] - **src**: move DiagnosticFilename inlines into a -inl.h (Sam Roberts) [#27839](https://github.com/nodejs/node/pull/27839)
+* [[`d774ea5cce`](https://github.com/nodejs/node/commit/d774ea5cce)] - **src**: remove env-inl.h from header files (Sam Roberts) [#27755](https://github.com/nodejs/node/pull/27755)
+* [[`02f794a53f`](https://github.com/nodejs/node/commit/02f794a53f)] - **src**: remove memory\_tracker-inl.h from header files (Sam Roberts) [#27755](https://github.com/nodejs/node/pull/27755)
+* [[`940577bd76`](https://github.com/nodejs/node/commit/940577bd76)] - **src**: move ThreadPoolWork inlines into a -inl.h (Sam Roberts) [#27755](https://github.com/nodejs/node/pull/27755)
+* [[`c0cf17388c`](https://github.com/nodejs/node/commit/c0cf17388c)] - **src**: ignore SIGXFSZ, don't terminate (ulimit -f) (Ben Noordhuis) [#27798](https://github.com/nodejs/node/pull/27798)
+* [[`a47ee80114`](https://github.com/nodejs/node/commit/a47ee80114)] - **(SEMVER-MINOR)** **stream**: convert string to Buffer when calling `unshift(\)` (Marcos Casagrande) [#27194](https://github.com/nodejs/node/pull/27194)
+* [[`5eccd642ef`](https://github.com/nodejs/node/commit/5eccd642ef)] - **stream**: convert existing buffer when calling .setEncoding (Anna Henningsen) [#27936](https://github.com/nodejs/node/pull/27936)
+* [[`6a5ce36fb8`](https://github.com/nodejs/node/commit/6a5ce36fb8)] - **test**: handle unknown message type in worker threads (Rich Trott) [#27995](https://github.com/nodejs/node/pull/27995)
+* [[`182725651b`](https://github.com/nodejs/node/commit/182725651b)] - **test**: add coverage for unserializable worker thread error (Rich Trott) [#27995](https://github.com/nodejs/node/pull/27995)
+* [[`887dd604f1`](https://github.com/nodejs/node/commit/887dd604f1)] - **test**: simplify fs promises test (Daniel Nalborczyk) [#27242](https://github.com/nodejs/node/pull/27242)
+* [[`9229825496`](https://github.com/nodejs/node/commit/9229825496)] - **test**: covering destroying when worker already disconnected (Keroosha) [#27896](https://github.com/nodejs/node/pull/27896)
+* [[`10bdd13972`](https://github.com/nodejs/node/commit/10bdd13972)] - **test**: rename test-performance to test-perf-hooks (Ujjwal Sharma) [#27969](https://github.com/nodejs/node/pull/27969)
+* [[`6129376cd9`](https://github.com/nodejs/node/commit/6129376cd9)] - **test**: add coverage for sparse array maxArrayLength (went.out) [#27901](https://github.com/nodejs/node/pull/27901)
+* [[`38e3827ca8`](https://github.com/nodejs/node/commit/38e3827ca8)] - **test**: add util inspect null getter test (Mikhail Kuklin) [#27884](https://github.com/nodejs/node/pull/27884)
+* [[`0e1ce2055e`](https://github.com/nodejs/node/commit/0e1ce2055e)] - **test**: rsa-pss generateKeyPairSync invalid option hash (Evgenii Shchepotev) [#27883](https://github.com/nodejs/node/pull/27883)
+* [[`0d74198123`](https://github.com/nodejs/node/commit/0d74198123)] - **test**: cover import of a \*.node file with a policy manifest (Evgenii Shchepotev) [#27903](https://github.com/nodejs/node/pull/27903)
+* [[`6f9aa3f722`](https://github.com/nodejs/node/commit/6f9aa3f722)] - **test**: add test cases for paramEncoding 'explicit' (oksana) [#27900](https://github.com/nodejs/node/pull/27900)
+* [[`682319f449`](https://github.com/nodejs/node/commit/682319f449)] - **test**: switch assertEqual arguments (Evgenii Shchepotev) [#27910](https://github.com/nodejs/node/pull/27910)
+* [[`b5b234deff`](https://github.com/nodejs/node/commit/b5b234deff)] - **test**: add testcase for SourceTextModule custom inspect (Grigory Gorshkov) [#27889](https://github.com/nodejs/node/pull/27889)
+* [[`630cc3ac30`](https://github.com/nodejs/node/commit/630cc3ac30)] - **test**: cover util.inspect on boxed primitive with colors (Alexander Avakov) [#27897](https://github.com/nodejs/node/pull/27897)
+* [[`67b692bdb9`](https://github.com/nodejs/node/commit/67b692bdb9)] - **test**: add test case for checking typeof mgf1Hash (Levin Eugene) [#27892](https://github.com/nodejs/node/pull/27892)
+* [[`2a509d40f4`](https://github.com/nodejs/node/commit/2a509d40f4)] - **test**: switch assertEqual arguments (Evgenii Shchepotev) [#27912](https://github.com/nodejs/node/pull/27912)
+* [[`3ba354aaaa`](https://github.com/nodejs/node/commit/3ba354aaaa)] - **test**: add test for util.inspect (Levin Eugene) [#27906](https://github.com/nodejs/node/pull/27906)
+* [[`313077ea62`](https://github.com/nodejs/node/commit/313077ea62)] - **test**: expect wpt/encoding/encodeInto.any.js to fail (Joyee Cheung) [#27860](https://github.com/nodejs/node/pull/27860)
+* [[`8fc6914d09`](https://github.com/nodejs/node/commit/8fc6914d09)] - **test**: update wpt/encoding to 7287608f90 (Joyee Cheung) [#27860](https://github.com/nodejs/node/pull/27860)
+* [[`0f86c2b185`](https://github.com/nodejs/node/commit/0f86c2b185)] - **test**: run WPT in subdirectories (Joyee Cheung) [#27860](https://github.com/nodejs/node/pull/27860)
+* [[`51ccdae445`](https://github.com/nodejs/node/commit/51ccdae445)] - **test**: expect wpt/encoding/streams to fail (Joyee Cheung) [#27860](https://github.com/nodejs/node/pull/27860)
+* [[`652cadba1c`](https://github.com/nodejs/node/commit/652cadba1c)] - **test**: fix arguments order of comparsion functions (martyns0n) [#27907](https://github.com/nodejs/node/pull/27907)
+* [[`b117f6d5d8`](https://github.com/nodejs/node/commit/b117f6d5d8)] - **test**: switch assertEqual arguments (Evgenii Shchepotev) [#27913](https://github.com/nodejs/node/pull/27913)
+* [[`e7966bcb80`](https://github.com/nodejs/node/commit/e7966bcb80)] - **test**: unhardcode server port (MurkyMeow) [#27908](https://github.com/nodejs/node/pull/27908)
+* [[`b83571d236`](https://github.com/nodejs/node/commit/b83571d236)] - **test**: add a test case for the path.posix.resolve (Grigorii K. Shartsev) [#27905](https://github.com/nodejs/node/pull/27905)
+* [[`f5bb1b380f`](https://github.com/nodejs/node/commit/f5bb1b380f)] - **test**: switch actual value argument and expected in deepStrictEqual call (Kopachyov Vitaliy) [#27888](https://github.com/nodejs/node/pull/27888)
+* [[`531669b917`](https://github.com/nodejs/node/commit/531669b917)] - **test**: fix test-http2-multiheaders-raw (Grigorii K. Shartsev) [#27885](https://github.com/nodejs/node/pull/27885)
+* [[`724d9c89bc`](https://github.com/nodejs/node/commit/724d9c89bc)] - **test**: change expected and actual values in assert call (oksana) [#27881](https://github.com/nodejs/node/pull/27881)
+* [[`34ef9e4a2b`](https://github.com/nodejs/node/commit/34ef9e4a2b)] - **test**: detect missing postmortem metadata (cjihrig) [#27828](https://github.com/nodejs/node/pull/27828)
+* [[`bfcbab4c0c`](https://github.com/nodejs/node/commit/bfcbab4c0c)] - **test**: fix test-https-agent-additional-options (Rich Trott) [#27830](https://github.com/nodejs/node/pull/27830)
+* [[`a4c1fd5ffc`](https://github.com/nodejs/node/commit/a4c1fd5ffc)] - **test**: refactor test-https-agent-additional-options (Rich Trott) [#27830](https://github.com/nodejs/node/pull/27830)
+* [[`17abc8c942`](https://github.com/nodejs/node/commit/17abc8c942)] - **test**: favor arrow functions for anonymous callbacks (Rich Trott) [#27830](https://github.com/nodejs/node/pull/27830)
+* [[`155b947251`](https://github.com/nodejs/node/commit/155b947251)] - **test**: replace flag with option (Rich Trott) [#27830](https://github.com/nodejs/node/pull/27830)
+* [[`144db48b6d`](https://github.com/nodejs/node/commit/144db48b6d)] - **test**: update wpt/url to 418f7fabeb (Joyee Cheung) [#27822](https://github.com/nodejs/node/pull/27822)
+* [[`65d4f734e0`](https://github.com/nodejs/node/commit/65d4f734e0)] - **test**: use ShellTestEnvironment in WPT (Joyee Cheung) [#27822](https://github.com/nodejs/node/pull/27822)
+* [[`a9a400e604`](https://github.com/nodejs/node/commit/a9a400e604)] - **test**: update wpt/resources to e1fddfbf80 (Joyee Cheung) [#27822](https://github.com/nodejs/node/pull/27822)
+* [[`8040d8b321`](https://github.com/nodejs/node/commit/8040d8b321)] - **test**: increase debugging information on failure (Rich Trott) [#27790](https://github.com/nodejs/node/pull/27790)
+* [[`6548b91835`](https://github.com/nodejs/node/commit/6548b91835)] - **tls**: trace errors can show up as SSL errors (Sam Roberts) [#27841](https://github.com/nodejs/node/pull/27841)
+* [[`0fe16edfab`](https://github.com/nodejs/node/commit/0fe16edfab)] - **tls**: group chunks into TLS segments (Alba Mendez) [#27861](https://github.com/nodejs/node/pull/27861)
+* [[`e8fa0671a4`](https://github.com/nodejs/node/commit/e8fa0671a4)] - **tls**: destroy trace BIO instead of leaking it (Sam Roberts) [#27834](https://github.com/nodejs/node/pull/27834)
+* [[`10e0d7f2ac`](https://github.com/nodejs/node/commit/10e0d7f2ac)] - **tls**: support the hints option (Luigi Pinca) [#27816](https://github.com/nodejs/node/pull/27816)
+* [[`4716caa12e`](https://github.com/nodejs/node/commit/4716caa12e)] - **tls**: set tlsSocket.servername as early as possible (oyyd) [#27759](https://github.com/nodejs/node/pull/27759)
+* [[`2ce24a9452`](https://github.com/nodejs/node/commit/2ce24a9452)] - **tools**: fix js2c regression (Refael Ackermann) [#27980](https://github.com/nodejs/node/pull/27980)
+* [[`a75a59d3e3`](https://github.com/nodejs/node/commit/a75a59d3e3)] - **tools**: update inspector\_protocol to 0aafd2 (Michaël Zasso) [#27770](https://github.com/nodejs/node/pull/27770)
+* [[`728bc2f59a`](https://github.com/nodejs/node/commit/728bc2f59a)] - **tools**: update dependencies in tools/doc (Rich Trott) [#27927](https://github.com/nodejs/node/pull/27927)
+* [[`b54f3e0405`](https://github.com/nodejs/node/commit/b54f3e0405)] - **tools**: edit .eslintrc.js for minor maintainability improvements (Rich Trott) [#27789](https://github.com/nodejs/node/pull/27789)
+
## 2019-05-22, Version 12.3.1 (Current), @BridgeAR
diff --git a/doc/guides/writing-tests.md b/doc/guides/writing-tests.md
index 7b1d168d85b2ff..b4d05e2811b254 100644
--- a/doc/guides/writing-tests.md
+++ b/doc/guides/writing-tests.md
@@ -424,6 +424,9 @@ will depend on what is being tested if this is required or not.
To generate a test coverage report, see the
[Test Coverage section of the Building guide][].
+Nightly coverage reports for the Node.js master branch are available at
+https://coverage.nodejs.org/.
+
[ASCII]: http://man7.org/linux/man-pages/man7/ascii.7.html
[Google Test]: https://github.com/google/googletest
[`common` module]: https://github.com/nodejs/node/blob/master/test/common/README.md
diff --git a/doc/node.1 b/doc/node.1
index ab715c0c1bfca2..14266a3f57382b 100644
--- a/doc/node.1
+++ b/doc/node.1
@@ -108,9 +108,6 @@ Requires Node.js to be built with
.It Fl -es-module-specifier-resolution
Select extension resolution algorithm for ES Modules; either 'explicit' (default) or 'node'
.
-.It Fl -experimental-json-modules
-Enable experimental JSON interop support for the ES Module loader.
-.
.It Fl -experimental-modules
Enable experimental ES module support and caching modules.
.
@@ -130,6 +127,9 @@ feature.
.It Fl -experimental-vm-modules
Enable experimental ES module support in VM module.
.
+.It Fl -experimental-wasm-modules
+Enable experimental WebAssembly module support.
+.
.It Fl -force-fips
Force FIPS-compliant crypto on startup
(Cannot be disabled from script code).
@@ -142,12 +142,37 @@ Enable experimental frozen intrinsics support.
.It Fl -heapsnapshot-signal Ns = Ns Ar signal
Generate heap snapshot on specified signal.
.
+.It Fl -heap-prof
+Start the V8 heap profiler on start up, and write the heap profile to disk
+before exit. If
+.Fl -heap-prof-dir
+is not specified, the profile will be written to the current working directory
+with a generated file name.
+.
+.It Fl -heap-prof-dir
+The directory where the heap profiles generated by
+.Fl -heap-prof
+will be placed.
+.
+.It Fl -heap-prof-interval
+The average sampling interval in bytes for the heap profiles generated by
+.Fl -heap-prof .
+The default is
+.Sy 512 * 1024 .
+.
+.It Fl -heap-prof-name
+File name of the V8 heap profile generated with
+.Fl -heap-prof
+.
.It Fl -http-parser Ns = Ns Ar library
Chooses an HTTP parser library. Available values are
.Sy llhttp
or
.Sy legacy .
.
+.It Fl -http-server-default-timeout Ns = Ns Ar milliseconds
+Overrides the default value for server socket timeout.
+.
.It Fl -icu-data-dir Ns = Ns Ar file
Specify ICU data load path.
Overrides
diff --git a/lib/_http_client.js b/lib/_http_client.js
index bc2c2af8acd609..5555db13623553 100644
--- a/lib/_http_client.js
+++ b/lib/_http_client.js
@@ -40,13 +40,14 @@ const { Buffer } = require('buffer');
const { defaultTriggerAsyncIdScope } = require('internal/async_hooks');
const { URL, urlToOptions, searchParamsSymbol } = require('internal/url');
const { outHeadersKey, ondrain } = require('internal/http');
+const { connResetException, codes } = require('internal/errors');
const {
ERR_HTTP_HEADERS_SENT,
ERR_INVALID_ARG_TYPE,
ERR_INVALID_HTTP_TOKEN,
ERR_INVALID_PROTOCOL,
ERR_UNESCAPED_CHARACTERS
-} = require('internal/errors').codes;
+} = codes;
const { getTimerDuration } = require('internal/timers');
const {
DTRACE_HTTP_CLIENT_REQUEST,
@@ -337,15 +338,6 @@ function emitAbortNT() {
this.emit('abort');
}
-
-function createHangUpError() {
- // eslint-disable-next-line no-restricted-syntax
- const error = new Error('socket hang up');
- error.code = 'ECONNRESET';
- return error;
-}
-
-
function socketCloseListener() {
const socket = this;
const req = socket._httpMessage;
@@ -381,7 +373,7 @@ function socketCloseListener() {
// receive a response. The error needs to
// fire on the request.
req.socket._hadError = true;
- req.emit('error', createHangUpError());
+ req.emit('error', connResetException('socket hang up'));
}
req.emit('close');
}
@@ -441,7 +433,7 @@ function socketOnEnd() {
// If we don't have a response then we know that the socket
// ended prematurely and we need to emit an error on the request.
req.socket._hadError = true;
- req.emit('error', createHangUpError());
+ req.emit('error', connResetException('socket hang up'));
}
if (parser) {
parser.finish();
@@ -719,10 +711,10 @@ function onSocketNT(req, socket) {
ClientRequest.prototype._deferToConnect = _deferToConnect;
function _deferToConnect(method, arguments_, cb) {
// This function is for calls that need to happen once the socket is
- // connected and writable. It's an important promisy thing for all the socket
- // calls that happen either now (when a socket is assigned) or
- // in the future (when a socket gets assigned out of the pool and is
- // eventually writable).
+ // assigned to this request and writable. It's an important promisy
+ // thing for all the socket calls that happen either now
+ // (when a socket is assigned) or in the future (when a socket gets
+ // assigned out of the pool and is eventually writable).
const callSocketMethod = () => {
if (method)
diff --git a/lib/_http_outgoing.js b/lib/_http_outgoing.js
index cb09e764fefdfb..a4a2b3ab144400 100644
--- a/lib/_http_outgoing.js
+++ b/lib/_http_outgoing.js
@@ -573,6 +573,7 @@ function write_(msg, chunk, encoding, callback, fromEnd) {
if (!msg._hasBody) {
debug('This type of response MUST NOT have a body. ' +
'Ignoring write() calls.');
+ if (callback) process.nextTick(callback);
return true;
}
diff --git a/lib/_http_server.js b/lib/_http_server.js
index 4a76f1a0884c6f..ff69c70c9ca353 100644
--- a/lib/_http_server.js
+++ b/lib/_http_server.js
@@ -55,8 +55,11 @@ const {
DTRACE_HTTP_SERVER_REQUEST,
DTRACE_HTTP_SERVER_RESPONSE
} = require('internal/dtrace');
+const { getOptionValue } = require('internal/options');
const kServerResponse = Symbol('ServerResponse');
+const kDefaultHttpServerTimeout =
+ getOptionValue('--http-server-default-timeout');
const STATUS_CODES = {
100: 'Continue',
@@ -315,7 +318,7 @@ function Server(options, requestListener) {
this.on('connection', connectionListener);
- this.timeout = 2 * 60 * 1000;
+ this.timeout = kDefaultHttpServerTimeout;
this.keepAliveTimeout = 5000;
this.maxHeadersCount = null;
this.headersTimeout = 40 * 1000; // 40 seconds
@@ -404,9 +407,10 @@ function connectionListenerInternal(server, socket) {
socket.on('resume', onSocketResume);
socket.on('pause', onSocketPause);
- // Override on to unconsume on `data`, `readable` listeners
- socket.on = socketOnWrap;
- socket.addListener = socket.on;
+ // Overrides to unconsume on `data`, `readable` listeners
+ socket.on = generateSocketListenerWrapper('on');
+ socket.addListener = generateSocketListenerWrapper('addListener');
+ socket.prependListener = generateSocketListenerWrapper('prependListener');
// We only consume the socket if it has never been consumed before.
if (socket._handle && socket._handle.isStreamBase &&
@@ -754,19 +758,21 @@ function unconsume(parser, socket) {
}
}
-function socketOnWrap(ev, fn) {
- const res = net.Socket.prototype.on.call(this, ev, fn);
- if (!this.parser) {
- this.prependListener = net.Socket.prototype.prependListener;
- this.on = net.Socket.prototype.on;
- this.addListener = this.on;
- return res;
- }
+function generateSocketListenerWrapper(originalFnName) {
+ return function socketListenerWrap(ev, fn) {
+ const res = net.Socket.prototype[originalFnName].call(this, ev, fn);
+ if (!this.parser) {
+ this.on = net.Socket.prototype.on;
+ this.addListener = net.Socket.prototype.addListener;
+ this.prependListener = net.Socket.prototype.prependListener;
+ return res;
+ }
- if (ev === 'data' || ev === 'readable')
- unconsume(this.parser, this);
+ if (ev === 'data' || ev === 'readable')
+ unconsume(this.parser, this);
- return res;
+ return res;
+ };
}
function resetHeadersTimeoutOnReqEnd() {
diff --git a/lib/_stream_readable.js b/lib/_stream_readable.js
index 5905c56bd4abd7..d6db7188750ebd 100644
--- a/lib/_stream_readable.js
+++ b/lib/_stream_readable.js
@@ -207,13 +207,28 @@ Readable.prototype._destroy = function(err, cb) {
// similar to how Writable.write() returns true if you should
// write() some more.
Readable.prototype.push = function(chunk, encoding) {
- const state = this._readableState;
- var skipChunkCheck;
+ return readableAddChunk(this, chunk, encoding, false);
+};
+
+// Unshift should *always* be something directly out of read()
+Readable.prototype.unshift = function(chunk, encoding) {
+ return readableAddChunk(this, chunk, encoding, true);
+};
+
+function readableAddChunk(stream, chunk, encoding, addToFront) {
+ debug('readableAddChunk', chunk);
+ const state = stream._readableState;
+
+ let skipChunkCheck;
if (!state.objectMode) {
if (typeof chunk === 'string') {
encoding = encoding || state.defaultEncoding;
- if (encoding !== state.encoding) {
+ if (addToFront && state.encoding && state.encoding !== encoding) {
+ // When unshifting, if state.encoding is set, we have to save
+ // the string in the BufferList with the state encoding
+ chunk = Buffer.from(chunk, encoding).toString(state.encoding);
+ } else if (encoding !== state.encoding) {
chunk = Buffer.from(chunk, encoding);
encoding = '';
}
@@ -223,17 +238,6 @@ Readable.prototype.push = function(chunk, encoding) {
skipChunkCheck = true;
}
- return readableAddChunk(this, chunk, encoding, false, skipChunkCheck);
-};
-
-// Unshift should *always* be something directly out of read()
-Readable.prototype.unshift = function(chunk) {
- return readableAddChunk(this, chunk, null, true, false);
-};
-
-function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) {
- debug('readableAddChunk', chunk);
- const state = stream._readableState;
if (chunk === null) {
state.reading = false;
onEofChunk(stream, state);
@@ -321,9 +325,22 @@ Readable.prototype.isPaused = function() {
Readable.prototype.setEncoding = function(enc) {
if (!StringDecoder)
StringDecoder = require('string_decoder').StringDecoder;
- this._readableState.decoder = new StringDecoder(enc);
+ const decoder = new StringDecoder(enc);
+ this._readableState.decoder = decoder;
// If setEncoding(null), decoder.encoding equals utf8
this._readableState.encoding = this._readableState.decoder.encoding;
+
+ // Iterate over current buffer to convert already stored Buffers:
+ let p = this._readableState.buffer.head;
+ let content = '';
+ while (p !== null) {
+ content += decoder.write(p.data);
+ p = p.next;
+ }
+ this._readableState.buffer.clear();
+ if (content !== '')
+ this._readableState.buffer.push(content);
+ this._readableState.length = content.length;
return this;
};
diff --git a/lib/_tls_wrap.js b/lib/_tls_wrap.js
index 618f3892cee83b..58ad741cbf2172 100644
--- a/lib/_tls_wrap.js
+++ b/lib/_tls_wrap.js
@@ -44,6 +44,7 @@ const tls_wrap = internalBinding('tls_wrap');
const { Pipe, constants: PipeConstants } = internalBinding('pipe_wrap');
const { owner_symbol } = require('internal/async_hooks').symbols;
const { SecureContext: NativeSecureContext } = internalBinding('crypto');
+const { connResetException, codes } = require('internal/errors');
const {
ERR_INVALID_ARG_TYPE,
ERR_INVALID_CALLBACK,
@@ -55,7 +56,7 @@ const {
ERR_TLS_REQUIRED_SERVER_NAME,
ERR_TLS_SESSION_ATTACK,
ERR_TLS_SNI_FROM_SERVER
-} = require('internal/errors').codes;
+} = codes;
const { getOptionValue } = require('internal/options');
const { validateString } = require('internal/validators');
const traceTls = getOptionValue('--trace-tls');
@@ -442,7 +443,7 @@ const proxiedMethods = [
'setSimultaneousAccepts', 'setBlocking',
// PipeWrap
- 'setPendingInstances'
+ 'setPendingInstances',
];
// Proxy HandleWrap, PipeWrap and TCPWrap methods
@@ -774,7 +775,10 @@ TLSSocket.prototype._finishInit = function() {
return;
this.alpnProtocol = this._handle.getALPNNegotiatedProtocol();
- this.servername = this._handle.getServername();
+ // The servername could be set by TLSWrap::SelectSNIContextCallback().
+ if (this.servername === null) {
+ this.servername = this._handle.getServername();
+ }
debug('%s _finishInit',
this._tlsOptions.isServer ? 'server' : 'client',
@@ -905,9 +909,7 @@ function onSocketClose(err) {
// Emit ECONNRESET
if (!this._controlReleased && !this[kErrorEmitted]) {
this[kErrorEmitted] = true;
- // eslint-disable-next-line no-restricted-syntax
- const connReset = new Error('socket hang up');
- connReset.code = 'ECONNRESET';
+ const connReset = connResetException('socket hang up');
this._tlsOptions.server.emit('tlsClientError', connReset, this);
}
}
@@ -1350,10 +1352,9 @@ function onConnectEnd() {
if (!this._hadError) {
const options = this[kConnectOptions];
this._hadError = true;
- // eslint-disable-next-line no-restricted-syntax
- const error = new Error('Client network socket disconnected before ' +
- 'secure TLS connection was established');
- error.code = 'ECONNRESET';
+ const error = connResetException('Client network socket disconnected ' +
+ 'before secure TLS connection was ' +
+ 'established');
error.path = options.path;
error.host = options.host;
error.port = options.port;
@@ -1417,23 +1418,13 @@ exports.connect = function connect(...args) {
tlssock.once('secureConnect', cb);
if (!options.socket) {
- // If user provided the socket, its their responsibility to manage its
+ // If user provided the socket, it's their responsibility to manage its
// connectivity. If we created one internally, we connect it.
- const connectOpt = {
- path: options.path,
- port: options.port,
- host: options.host,
- family: options.family,
- localAddress: options.localAddress,
- localPort: options.localPort,
- lookup: options.lookup
- };
-
if (options.timeout) {
tlssock.setTimeout(options.timeout);
}
- tlssock.connect(connectOpt, tlssock._start);
+ tlssock.connect(options, tlssock._start);
}
tlssock._releaseControl();
diff --git a/lib/child_process.js b/lib/child_process.js
index 26965aa6b9c504..66be7611dc9587 100644
--- a/lib/child_process.js
+++ b/lib/child_process.js
@@ -51,9 +51,7 @@ const {
const MAX_BUFFER = 1024 * 1024;
-exports.ChildProcess = ChildProcess;
-
-exports.fork = function fork(modulePath /* , args, options */) {
+function fork(modulePath /* , args, options */) {
validateString(modulePath, 'modulePath');
// Get options and args arguments.
@@ -108,10 +106,9 @@ exports.fork = function fork(modulePath /* , args, options */) {
options.shell = false;
return spawn(options.execPath, args, options);
-};
-
+}
-exports._forkChild = function _forkChild(fd) {
+function _forkChild(fd) {
// set process.send()
const p = new Pipe(PipeConstants.IPC);
p.open(fd);
@@ -123,8 +120,7 @@ exports._forkChild = function _forkChild(fd) {
process.on('removeListener', function onRemoveListener(name) {
if (name === 'message' || name === 'disconnect') control.unref();
});
-};
-
+}
function normalizeExecArgs(command, options, callback) {
if (typeof options === 'function') {
@@ -144,12 +140,12 @@ function normalizeExecArgs(command, options, callback) {
}
-exports.exec = function exec(command, options, callback) {
+function exec(command, options, callback) {
const opts = normalizeExecArgs(command, options, callback);
- return exports.execFile(opts.file,
- opts.options,
- opts.callback);
-};
+ return module.exports.execFile(opts.file,
+ opts.options,
+ opts.callback);
+}
const customPromiseExecFunction = (orig) => {
return (...args) => {
@@ -167,12 +163,12 @@ const customPromiseExecFunction = (orig) => {
};
};
-Object.defineProperty(exports.exec, promisify.custom, {
+Object.defineProperty(exec, promisify.custom, {
enumerable: false,
- value: customPromiseExecFunction(exports.exec)
+ value: customPromiseExecFunction(exec)
});
-exports.execFile = function execFile(file /* , args, options, callback */) {
+function execFile(file /* , args, options, callback */) {
let args = [];
let callback;
let options;
@@ -386,11 +382,11 @@ exports.execFile = function execFile(file /* , args, options, callback */) {
child.addListener('error', errorhandler);
return child;
-};
+}
-Object.defineProperty(exports.execFile, promisify.custom, {
+Object.defineProperty(execFile, promisify.custom, {
enumerable: false,
- value: customPromiseExecFunction(exports.execFile)
+ value: customPromiseExecFunction(execFile)
});
function normalizeSpawnArguments(file, args, options) {
@@ -529,7 +525,7 @@ function normalizeSpawnArguments(file, args, options) {
}
-var spawn = exports.spawn = function spawn(file, args, options) {
+function spawn(file, args, options) {
const opts = normalizeSpawnArguments(file, args, options);
const child = new ChildProcess();
@@ -550,7 +546,7 @@ var spawn = exports.spawn = function spawn(file, args, options) {
});
return child;
-};
+}
function spawnSync(file, args, options) {
const opts = normalizeSpawnArguments(file, args, options);
@@ -559,7 +555,7 @@ function spawnSync(file, args, options) {
maxBuffer: MAX_BUFFER,
...opts.options
};
- options = opts.options = Object.assign(defaults, opts.options);
+ options = opts.options = defaults;
debug('spawnSync', opts.args, options);
@@ -605,7 +601,6 @@ function spawnSync(file, args, options) {
return child_process.spawnSync(opts);
}
-exports.spawnSync = spawnSync;
function checkExecSyncError(ret, args, cmd) {
@@ -643,7 +638,6 @@ function execFileSync(command, args, options) {
return ret.stdout;
}
-exports.execFileSync = execFileSync;
function execSync(command, options) {
@@ -662,7 +656,6 @@ function execSync(command, options) {
return ret.stdout;
}
-exports.execSync = execSync;
function validateTimeout(timeout) {
@@ -690,3 +683,15 @@ function sanitizeKillSignal(killSignal) {
killSignal);
}
}
+
+module.exports = {
+ _forkChild,
+ ChildProcess,
+ exec,
+ execFile,
+ execFileSync,
+ execSync,
+ fork,
+ spawn,
+ spawnSync
+};
diff --git a/lib/fs.js b/lib/fs.js
index 7a31e26ccb1401..e890d0c1305b95 100644
--- a/lib/fs.js
+++ b/lib/fs.js
@@ -75,8 +75,7 @@ const {
validateOffsetLengthRead,
validateOffsetLengthWrite,
validatePath,
- warnOnNonPortableTemplate,
- handleErrorFromBinding
+ warnOnNonPortableTemplate
} = require('internal/fs/utils');
const {
CHAR_FORWARD_SLASH,
@@ -119,6 +118,23 @@ function showTruncateDeprecation() {
}
}
+function handleErrorFromBinding(ctx) {
+ if (ctx.errno !== undefined) { // libuv error numbers
+ const err = uvException(ctx);
+ // eslint-disable-next-line no-restricted-syntax
+ Error.captureStackTrace(err, handleErrorFromBinding);
+ throw err;
+ }
+ if (ctx.error !== undefined) { // Errors created in C++ land.
+ // TODO(joyeecheung): currently, ctx.error are encoding errors
+ // usually caused by memory problems. We need to figure out proper error
+ // code(s) for this.
+ // eslint-disable-next-line no-restricted-syntax
+ Error.captureStackTrace(ctx.error, handleErrorFromBinding);
+ throw ctx.error;
+ }
+}
+
function maybeCallback(cb) {
if (typeof cb === 'function')
return cb;
@@ -1517,11 +1533,9 @@ realpathSync.native = (path, options) => {
function realpath(p, options, callback) {
callback = typeof options === 'function' ? options : maybeCallback(callback);
- if (!options)
- options = emptyObj;
- else
- options = getOptions(options, emptyObj);
+ options = getOptions(options, {});
p = toPathIfFileURL(p);
+
if (typeof p !== 'string') {
p += '';
}
diff --git a/lib/https.js b/lib/https.js
index 4e649017312a24..44b885b0a42891 100644
--- a/lib/https.js
+++ b/lib/https.js
@@ -38,6 +38,10 @@ const debug = require('internal/util/debuglog').debuglog('https');
const { URL, urlToOptions, searchParamsSymbol } = require('internal/url');
const { IncomingMessage, ServerResponse } = require('http');
const { kIncomingMessage } = require('_http_common');
+const { getOptionValue } = require('internal/options');
+
+const kDefaultHttpServerTimeout =
+ getOptionValue('--http-server-default-timeout');
function Server(opts, requestListener) {
if (!(this instanceof Server)) return new Server(opts, requestListener);
@@ -71,7 +75,7 @@ function Server(opts, requestListener) {
conn.destroy(err);
});
- this.timeout = 2 * 60 * 1000;
+ this.timeout = kDefaultHttpServerTimeout;
this.keepAliveTimeout = 5000;
this.maxHeadersCount = null;
this.headersTimeout = 40 * 1000; // 40 seconds
diff --git a/lib/inspector.js b/lib/inspector.js
index 33c48125bbd22e..4bec628b7d789e 100644
--- a/lib/inspector.js
+++ b/lib/inspector.js
@@ -37,12 +37,8 @@ class Session extends EventEmitter {
connect() {
if (this[connectionSymbol])
throw new ERR_INSPECTOR_ALREADY_CONNECTED('The inspector session');
- const connection =
+ this[connectionSymbol] =
new Connection((message) => this[onMessageSymbol](message));
- if (connection.sessionAttached) {
- throw new ERR_INSPECTOR_ALREADY_CONNECTED('Another inspector session');
- }
- this[connectionSymbol] = connection;
}
[onMessageSymbol](message) {
diff --git a/lib/internal/assert/assertion_error.js b/lib/internal/assert/assertion_error.js
index 7b62fca0352f5d..18d9951af0ddf0 100644
--- a/lib/internal/assert/assertion_error.js
+++ b/lib/internal/assert/assertion_error.js
@@ -374,9 +374,9 @@ class AssertionError extends Error {
} else {
let res = inspectValue(actual);
let other = inspectValue(expected);
- const knownOperators = kReadableOperator[operator];
+ const knownOperator = kReadableOperator[operator];
if (operator === 'notDeepEqual' && res === other) {
- res = `${knownOperators}\n\n${res}`;
+ res = `${knownOperator}\n\n${res}`;
if (res.length > 1024) {
res = `${res.slice(0, 1021)}...`;
}
@@ -389,13 +389,11 @@ class AssertionError extends Error {
other = `${other.slice(0, 509)}...`;
}
if (operator === 'deepEqual') {
- const eq = operator === 'deepEqual' ? 'deep-equal' : 'equal';
- res = `${knownOperators}\n\n${res}\n\nshould loosely ${eq}\n\n`;
+ res = `${knownOperator}\n\n${res}\n\nshould loosely deep-equal\n\n`;
} else {
- const newOperator = kReadableOperator[`${operator}Unequal`];
- if (newOperator) {
- const eq = operator === 'notDeepEqual' ? 'deep-equal' : 'equal';
- res = `${newOperator}\n\n${res}\n\nshould not loosely ${eq}\n\n`;
+ const newOp = kReadableOperator[`${operator}Unequal`];
+ if (newOp) {
+ res = `${newOp}\n\n${res}\n\nshould not loosely deep-equal\n\n`;
} else {
other = ` ${operator} ${other}`;
}
diff --git a/lib/internal/console/constructor.js b/lib/internal/console/constructor.js
index 9c262aef62be25..e3de39f8126b7c 100644
--- a/lib/internal/console/constructor.js
+++ b/lib/internal/console/constructor.js
@@ -412,6 +412,7 @@ const consoleMethods = {
const opt = {
depth,
maxArrayLength: 3,
+ breakLength: Infinity,
...this[kGetInspectOptions](this._stdout)
};
return inspect(v, opt);
diff --git a/lib/internal/crypto/keys.js b/lib/internal/crypto/keys.js
index 321506eaf4a531..fb17ba36ced0e3 100644
--- a/lib/internal/crypto/keys.js
+++ b/lib/internal/crypto/keys.js
@@ -44,7 +44,7 @@ class KeyObject {
if (type !== 'secret' && type !== 'public' && type !== 'private')
throw new ERR_INVALID_ARG_VALUE('type', type);
if (typeof handle !== 'object')
- throw new ERR_INVALID_ARG_TYPE('handle', 'string', handle);
+ throw new ERR_INVALID_ARG_TYPE('handle', 'object', handle);
this[kKeyType] = type;
diff --git a/lib/internal/errors.js b/lib/internal/errors.js
index 266358310bf3f7..f4f4ee09be3f97 100644
--- a/lib/internal/errors.js
+++ b/lib/internal/errors.js
@@ -554,6 +554,13 @@ function dnsException(code, syscall, hostname) {
return ex;
}
+function connResetException(msg) {
+ // eslint-disable-next-line no-restricted-syntax
+ const ex = new Error(msg);
+ ex.code = 'ECONNRESET';
+ return ex;
+}
+
let maxStack_ErrorName;
let maxStack_ErrorMessage;
/**
@@ -619,6 +626,7 @@ module.exports = {
getMessage,
hideStackFrames,
isStackOverflowError,
+ connResetException,
uvException,
uvExceptionWithHostPort,
SystemError,
diff --git a/lib/internal/fs/utils.js b/lib/internal/fs/utils.js
index 4cb06690bf558f..14abad81ec4e54 100644
--- a/lib/internal/fs/utils.js
+++ b/lib/internal/fs/utils.js
@@ -12,8 +12,7 @@ const {
ERR_INVALID_OPT_VALUE_ENCODING,
ERR_OUT_OF_RANGE
},
- hideStackFrames,
- uvException
+ hideStackFrames
} = require('internal/errors');
const {
isUint8Array,
@@ -452,26 +451,7 @@ function warnOnNonPortableTemplate(template) {
}
}
-// This handles errors following the convention of the fs binding.
-function handleErrorFromBinding(ctx) {
- if (ctx.errno !== undefined) { // libuv error numbers
- const err = uvException(ctx);
- // eslint-disable-next-line no-restricted-syntax
- Error.captureStackTrace(err, handleErrorFromBinding);
- throw err;
- }
- if (ctx.error !== undefined) { // Errors created in C++ land.
- // TODO(joyeecheung): currently, ctx.error are encoding errors
- // usually caused by memory problems. We need to figure out proper error
- // code(s) for this.
- // eslint-disable-next-line no-restricted-syntax
- Error.captureStackTrace(ctx.error, handleErrorFromBinding);
- throw ctx.error;
- }
-}
-
module.exports = {
- handleErrorFromBinding,
assertEncoding,
copyObject,
Dirent,
diff --git a/lib/internal/http2/core.js b/lib/internal/http2/core.js
index 3beab54ae4ca77..b1e5d4cef55392 100644
--- a/lib/internal/http2/core.js
+++ b/lib/internal/http2/core.js
@@ -137,6 +137,7 @@ const { UV_EOF } = internalBinding('uv');
const { StreamPipe } = internalBinding('stream_pipe');
const { _connectionListener: httpConnectionListener } = http;
const debug = require('internal/util/debuglog').debuglog('http2');
+const { getOptionValue } = require('internal/options');
const kMaxFrameSize = (2 ** 24) - 1;
const kMaxInt = (2 ** 32) - 1;
@@ -171,7 +172,8 @@ const kState = Symbol('state');
const kType = Symbol('type');
const kWriteGeneric = Symbol('write-generic');
-const kDefaultSocketTimeout = 2 * 60 * 1000;
+const kDefaultHttpServerTimeout =
+ getOptionValue('--http-server-default-timeout');
const {
paddingBuffer,
@@ -1071,6 +1073,9 @@ class Http2Session extends EventEmitter {
}
[kInspect](depth, opts) {
+ if (typeof depth === 'number' && depth < 0)
+ return this;
+
const obj = {
type: this[kType],
closed: this.closed,
@@ -1647,6 +1652,9 @@ class Http2Stream extends Duplex {
}
[kInspect](depth, opts) {
+ if (typeof depth === 'number' && depth < 0)
+ return this;
+
const obj = {
id: this[kID] || '',
closed: this.closed,
@@ -2679,7 +2687,7 @@ class Http2SecureServer extends TLSServer {
options = initializeTLSOptions(options);
super(options, connectionListener);
this[kOptions] = options;
- this.timeout = kDefaultSocketTimeout;
+ this.timeout = kDefaultHttpServerTimeout;
this.on('newListener', setupCompat);
if (typeof requestListener === 'function')
this.on('request', requestListener);
@@ -2699,9 +2707,10 @@ class Http2SecureServer extends TLSServer {
class Http2Server extends NETServer {
constructor(options, requestListener) {
- super(connectionListener);
- this[kOptions] = initializeOptions(options);
- this.timeout = kDefaultSocketTimeout;
+ options = initializeOptions(options);
+ super(options, connectionListener);
+ this[kOptions] = options;
+ this.timeout = kDefaultHttpServerTimeout;
this.on('newListener', setupCompat);
if (typeof requestListener === 'function')
this.on('request', requestListener);
diff --git a/lib/internal/main/repl.js b/lib/internal/main/repl.js
index b38102a15482fd..93b932f0bdd15f 100644
--- a/lib/internal/main/repl.js
+++ b/lib/internal/main/repl.js
@@ -11,7 +11,7 @@ const {
evalScript
} = require('internal/process/execution');
-const { print, kStderr, kStdout } = require('internal/util/print');
+const console = require('internal/console/global');
const { getOptionValue } = require('internal/options');
@@ -21,12 +21,14 @@ markBootstrapComplete();
// --input-type flag not supported in REPL
if (getOptionValue('--input-type')) {
- print(kStderr, 'Cannot specify --input-type for REPL');
+ // If we can't write to stderr, we'd like to make this a noop,
+ // so use console.error.
+ console.error('Cannot specify --input-type for REPL');
process.exit(1);
}
-print(kStdout, `Welcome to Node.js ${process.version}.\n` +
- 'Type ".help" for more information.');
+console.log(`Welcome to Node.js ${process.version}.\n` +
+ 'Type ".help" for more information.');
const cliRepl = require('internal/repl');
cliRepl.createInternalRepl(process.env, (err, repl) => {
diff --git a/lib/internal/modules/esm/create_dynamic_module.js b/lib/internal/modules/esm/create_dynamic_module.js
index 45f964d5ad8020..1201820003984f 100644
--- a/lib/internal/modules/esm/create_dynamic_module.js
+++ b/lib/internal/modules/esm/create_dynamic_module.js
@@ -4,24 +4,27 @@ const { ArrayPrototype, JSON, Object } = primordials;
const debug = require('internal/util/debuglog').debuglog('esm');
-const createDynamicModule = (imports, exports, url = '', evaluate) => {
- debug('creating ESM facade for %s with exports: %j', url, exports);
- const names = ArrayPrototype.map(exports, (name) => `${name}`);
-
- const source = `
-${ArrayPrototype.join(ArrayPrototype.map(imports, (impt, index) =>
- `import * as $import_${index} from ${JSON.stringify(impt)};
-import.meta.imports[${JSON.stringify(impt)}] = $import_${index};`), '\n')
+function createImport(impt, index) {
+ const imptPath = JSON.stringify(impt);
+ return `import * as $import_${index} from ${imptPath};
+import.meta.imports[${imptPath}] = $import_${index};`;
}
-${ArrayPrototype.join(ArrayPrototype.map(names, (name) =>
- `let $${name};
+
+function createExport(expt) {
+ const name = `${expt}`;
+ return `let $${name};
export { $${name} as ${name} };
import.meta.exports.${name} = {
get: () => $${name},
set: (v) => $${name} = v,
-};`), '\n')
+};`;
}
+const createDynamicModule = (imports, exports, url = '', evaluate) => {
+ debug('creating ESM facade for %s with exports: %j', url, exports);
+ const source = `
+${ArrayPrototype.join(ArrayPrototype.map(imports, createImport), '\n')}
+${ArrayPrototype.join(ArrayPrototype.map(exports, createExport), '\n')}
import.meta.done();
`;
const { ModuleWrap, callbackMap } = internalBinding('module_wrap');
diff --git a/lib/internal/modules/esm/default_resolve.js b/lib/internal/modules/esm/default_resolve.js
index 88377689ce4fd7..46e7b2415a92e0 100644
--- a/lib/internal/modules/esm/default_resolve.js
+++ b/lib/internal/modules/esm/default_resolve.js
@@ -8,7 +8,6 @@ const { getOptionValue } = require('internal/options');
const preserveSymlinks = getOptionValue('--preserve-symlinks');
const preserveSymlinksMain = getOptionValue('--preserve-symlinks-main');
-const experimentalJsonModules = getOptionValue('--experimental-json-modules');
const typeFlag = getOptionValue('--input-type');
const experimentalWasmModules = getOptionValue('--experimental-wasm-modules');
const { resolve: moduleWrapResolve,
@@ -29,6 +28,7 @@ const extensionFormatMap = {
'__proto__': null,
'.cjs': 'commonjs',
'.js': 'module',
+ '.json': 'json',
'.mjs': 'module'
};
@@ -36,7 +36,7 @@ const legacyExtensionFormatMap = {
'__proto__': null,
'.cjs': 'commonjs',
'.js': 'commonjs',
- '.json': 'commonjs',
+ '.json': 'json',
'.mjs': 'module',
'.node': 'commonjs'
};
@@ -44,9 +44,6 @@ const legacyExtensionFormatMap = {
if (experimentalWasmModules)
extensionFormatMap['.wasm'] = legacyExtensionFormatMap['.wasm'] = 'wasm';
-if (experimentalJsonModules)
- extensionFormatMap['.json'] = legacyExtensionFormatMap['.json'] = 'json';
-
function resolve(specifier, parentURL) {
if (NativeModule.canBeRequiredByUsers(specifier)) {
return {
diff --git a/lib/internal/process/execution.js b/lib/internal/process/execution.js
index 227c1c2149cef5..2b7fc41ccddf01 100644
--- a/lib/internal/process/execution.js
+++ b/lib/internal/process/execution.js
@@ -35,22 +35,24 @@ function tryGetCwd() {
}
}
-function evalModule(source, printResult) {
+function evalModule(source, print) {
+ const { log, error } = require('internal/console/global');
const { decorateErrorStack } = require('internal/util');
const asyncESM = require('internal/process/esm_loader');
- const { kStdout, kStderr, print } = require('internal/util/print');
asyncESM.loaderPromise.then(async (loader) => {
const { result } = await loader.eval(source);
- if (printResult) { print(kStdout, result); }
+ if (print) {
+ log(result);
+ }
})
.catch((e) => {
decorateErrorStack(e);
- print(kStderr, e);
+ error(e);
process.exit(1);
});
}
-function evalScript(name, body, breakFirstLine, printResult) {
+function evalScript(name, body, breakFirstLine, print) {
const CJSModule = require('internal/modules/cjs/loader');
const { kVmBreakFirstLineSymbol } = require('internal/util');
@@ -76,9 +78,9 @@ function evalScript(name, body, breakFirstLine, printResult) {
[kVmBreakFirstLineSymbol]: ${!!breakFirstLine}
});\n`;
const result = module._compile(script, `${name}-wrapper`);
- if (printResult) {
- const { kStdout, print } = require('internal/util/print');
- print(kStdout, result);
+ if (print) {
+ const { log } = require('internal/console/global');
+ log(result);
}
if (origModule !== undefined)
diff --git a/lib/internal/util/print.js b/lib/internal/util/print.js
deleted file mode 100644
index 4c9327502ebad2..00000000000000
--- a/lib/internal/util/print.js
+++ /dev/null
@@ -1,67 +0,0 @@
-'use strict';
-
-// This implements a light-weight printer that writes to stdout/stderr
-// directly to avoid the overhead in the console abstraction.
-
-const { formatWithOptions } = require('internal/util/inspect');
-const { writeString } = internalBinding('fs');
-const { handleErrorFromBinding } = require('internal/fs/utils');
-const { guessHandleType } = internalBinding('util');
-const { log } = require('internal/console/global');
-
-const kStdout = 1;
-const kStderr = 2;
-const handleType = [undefined, undefined, undefined];
-function getFdType(fd) {
- if (handleType[fd] === undefined) {
- handleType[fd] = guessHandleType(fd);
- }
- return handleType[fd];
-}
-
-function formatAndWrite(fd, obj, ignoreErrors, colors = false) {
- const str = `${formatWithOptions({ colors }, obj)}\n`;
- const ctx = {};
- writeString(fd, str, null, undefined, undefined, ctx);
- if (!ignoreErrors) {
- handleErrorFromBinding(ctx);
- }
-}
-
-let colors;
-function getColors() {
- if (colors === undefined) {
- colors = require('internal/tty').getColorDepth() > 2;
- }
- return colors;
-}
-
-// TODO(joyeecheung): replace more internal process._rawDebug()
-// and console.log() usage with this if possible.
-function print(fd, obj, ignoreErrors = true) {
- switch (getFdType(fd)) {
- case 'TTY':
- formatAndWrite(fd, obj, ignoreErrors, getColors());
- break;
- case 'FILE':
- formatAndWrite(fd, obj, ignoreErrors);
- break;
- case 'PIPE':
- case 'TCP':
- // Fallback to console.log to handle IPC.
- if (process.channel && process.channel.fd === fd) {
- log(obj);
- } else {
- formatAndWrite(fd, obj, ignoreErrors);
- }
- break;
- default:
- log(obj);
- }
-}
-
-module.exports = {
- print,
- kStderr,
- kStdout
-};
diff --git a/lib/v8.js b/lib/v8.js
index 2bede41291a947..cbb8229c7dd914 100644
--- a/lib/v8.js
+++ b/lib/v8.js
@@ -109,7 +109,9 @@ const {
kSpaceSizeIndex,
kSpaceUsedSizeIndex,
kSpaceAvailableSizeIndex,
- kPhysicalSpaceSizeIndex
+ kPhysicalSpaceSizeIndex,
+ kNumberOfNativeContextsIndex,
+ kNumberOfDetachedContextsIndex
} = internalBinding('v8');
const kNumberOfHeapSpaces = kHeapSpaces.length;
@@ -139,7 +141,9 @@ function getHeapStatistics() {
'heap_size_limit': buffer[kHeapSizeLimitIndex],
'malloced_memory': buffer[kMallocedMemoryIndex],
'peak_malloced_memory': buffer[kPeakMallocedMemoryIndex],
- 'does_zap_garbage': buffer[kDoesZapGarbageIndex]
+ 'does_zap_garbage': buffer[kDoesZapGarbageIndex],
+ 'number_of_native_contexts': buffer[kNumberOfNativeContextsIndex],
+ 'number_of_detached_contexts': buffer[kNumberOfDetachedContextsIndex]
};
}
diff --git a/node.gyp b/node.gyp
index df70d26f35f4e7..198a7ec166aa07 100644
--- a/node.gyp
+++ b/node.gyp
@@ -184,7 +184,6 @@
'lib/internal/url.js',
'lib/internal/util.js',
'lib/internal/util/comparisons.js',
- 'lib/internal/util/print.js',
'lib/internal/util/debuglog.js',
'lib/internal/util/inspect.js',
'lib/internal/util/inspector.js',
@@ -283,6 +282,14 @@
'ImageHasSafeExceptionHandlers': 'false',
},
},
+
+ 'conditions': [
+ ['OS=="aix"', {
+ 'ldflags': [
+ '-Wl,-bnoerrmsg',
+ ],
+ }],
+ ],
},
'targets': [
@@ -1083,6 +1090,7 @@
'test/cctest/test_node_postmortem_metadata.cc',
'test/cctest/test_environment.cc',
'test/cctest/test_linked_binding.cc',
+ 'test/cctest/test_per_process.cc',
'test/cctest/test_platform.cc',
'test/cctest/test_report_util.cc',
'test/cctest/test_traced_value.cc',
diff --git a/src/api/environment.cc b/src/api/environment.cc
index 5dfac00647eddd..eeeef7442d834a 100644
--- a/src/api/environment.cc
+++ b/src/api/environment.cc
@@ -1,4 +1,3 @@
-#include "env.h"
#include "node.h"
#include "node_context_data.h"
#include "node_errors.h"
diff --git a/src/base_object.h b/src/base_object.h
index cb83462ff51e54..f616108a1d9486 100644
--- a/src/base_object.h
+++ b/src/base_object.h
@@ -24,7 +24,7 @@
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
-#include "memory_tracker-inl.h"
+#include "memory_tracker.h"
#include "v8.h"
#include // std::remove_reference
diff --git a/src/cares_wrap.cc b/src/cares_wrap.cc
index 07882a4212c6b2..0be02596f96945 100644
--- a/src/cares_wrap.cc
+++ b/src/cares_wrap.cc
@@ -23,6 +23,7 @@
#include "ares.h"
#include "async_wrap-inl.h"
#include "env-inl.h"
+#include "memory_tracker-inl.h"
#include "node.h"
#include "req_wrap-inl.h"
#include "util-inl.h"
diff --git a/src/debug_utils.cc b/src/debug_utils.cc
index b86710fba6e85b..a9bfa86b6d2aea 100644
--- a/src/debug_utils.cc
+++ b/src/debug_utils.cc
@@ -1,4 +1,5 @@
#include "debug_utils.h"
+#include "env-inl.h"
#include "util-inl.h"
#ifdef __POSIX__
diff --git a/src/debug_utils.h b/src/debug_utils.h
index ef5a4c0c47590c..db01cacba6a1b6 100644
--- a/src/debug_utils.h
+++ b/src/debug_utils.h
@@ -4,7 +4,7 @@
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
#include "async_wrap.h"
-#include "env-inl.h"
+#include "env.h"
#include
#include
diff --git a/src/diagnosticfilename-inl.h b/src/diagnosticfilename-inl.h
new file mode 100644
index 00000000000000..58a3a933acc605
--- /dev/null
+++ b/src/diagnosticfilename-inl.h
@@ -0,0 +1,33 @@
+#ifndef SRC_DIAGNOSTICFILENAME_INL_H_
+#define SRC_DIAGNOSTICFILENAME_INL_H_
+
+#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
+
+#include "node_internals.h"
+#include "env-inl.h"
+
+namespace node {
+
+inline DiagnosticFilename::DiagnosticFilename(
+ Environment* env,
+ const char* prefix,
+ const char* ext) :
+ filename_(MakeFilename(env->thread_id(), prefix, ext)) {
+}
+
+inline DiagnosticFilename::DiagnosticFilename(
+ uint64_t thread_id,
+ const char* prefix,
+ const char* ext) :
+ filename_(MakeFilename(thread_id, prefix, ext)) {
+}
+
+inline const char* DiagnosticFilename::operator*() const {
+ return filename_.c_str();
+}
+
+} // namespace node
+
+#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
+
+#endif // SRC_DIAGNOSTICFILENAME_INL_H_
diff --git a/src/env-inl.h b/src/env-inl.h
index 4765d0db98525a..2239412ccac9cb 100644
--- a/src/env-inl.h
+++ b/src/env-inl.h
@@ -689,6 +689,41 @@ inline const std::string& Environment::cpu_prof_dir() const {
return cpu_prof_dir_;
}
+inline void Environment::set_heap_profiler_connection(
+ std::unique_ptr connection) {
+ CHECK_NULL(heap_profiler_connection_);
+ std::swap(heap_profiler_connection_, connection);
+}
+
+inline profiler::V8HeapProfilerConnection*
+Environment::heap_profiler_connection() {
+ return heap_profiler_connection_.get();
+}
+
+inline void Environment::set_heap_prof_name(const std::string& name) {
+ heap_prof_name_ = name;
+}
+
+inline const std::string& Environment::heap_prof_name() const {
+ return heap_prof_name_;
+}
+
+inline void Environment::set_heap_prof_dir(const std::string& dir) {
+ heap_prof_dir_ = dir;
+}
+
+inline const std::string& Environment::heap_prof_dir() const {
+ return heap_prof_dir_;
+}
+
+inline void Environment::set_heap_prof_interval(uint64_t interval) {
+ heap_prof_interval_ = interval;
+}
+
+inline uint64_t Environment::heap_prof_interval() const {
+ return heap_prof_interval_;
+}
+
#endif // HAVE_INSPECTOR
inline std::shared_ptr Environment::inspector_host_port() {
diff --git a/src/env.cc b/src/env.cc
index 5f408f18f146a4..bc43fac963bbc3 100644
--- a/src/env.cc
+++ b/src/env.cc
@@ -1,6 +1,7 @@
#include "env.h"
#include "async_wrap.h"
+#include "memory_tracker-inl.h"
#include "node_buffer.h"
#include "node_context_data.h"
#include "node_errors.h"
diff --git a/src/env.h b/src/env.h
index 5544ac44db5f8a..0c6dbe3c8f581f 100644
--- a/src/env.h
+++ b/src/env.h
@@ -73,6 +73,7 @@ class AgentWriterHandle;
namespace profiler {
class V8CoverageConnection;
class V8CpuProfilerConnection;
+class V8HeapProfilerConnection;
} // namespace profiler
#endif // HAVE_INSPECTOR
@@ -1151,6 +1152,20 @@ class Environment : public MemoryRetainer {
inline void set_cpu_prof_dir(const std::string& dir);
inline const std::string& cpu_prof_dir() const;
+
+ void set_heap_profiler_connection(
+ std::unique_ptr connection);
+ profiler::V8HeapProfilerConnection* heap_profiler_connection();
+
+ inline void set_heap_prof_name(const std::string& name);
+ inline const std::string& heap_prof_name() const;
+
+ inline void set_heap_prof_dir(const std::string& dir);
+ inline const std::string& heap_prof_dir() const;
+
+ inline void set_heap_prof_interval(uint64_t interval);
+ inline uint64_t heap_prof_interval() const;
+
#endif // HAVE_INSPECTOR
private:
@@ -1190,6 +1205,10 @@ class Environment : public MemoryRetainer {
std::string cpu_prof_dir_;
std::string cpu_prof_name_;
uint64_t cpu_prof_interval_;
+ std::unique_ptr heap_profiler_connection_;
+ std::string heap_prof_dir_;
+ std::string heap_prof_name_;
+ uint64_t heap_prof_interval_;
#endif // HAVE_INSPECTOR
std::shared_ptr options_;
diff --git a/src/heap_utils.cc b/src/heap_utils.cc
index ee0665cfe279d8..8391f1de3726c1 100644
--- a/src/heap_utils.cc
+++ b/src/heap_utils.cc
@@ -1,4 +1,6 @@
+#include "diagnosticfilename-inl.h"
#include "env-inl.h"
+#include "memory_tracker-inl.h"
#include "stream_base-inl.h"
#include "util-inl.h"
diff --git a/src/inspector/node_inspector.gypi b/src/inspector/node_inspector.gypi
index 2ee8cfd7dafe3f..1d1dbefd866645 100644
--- a/src/inspector/node_inspector.gypi
+++ b/src/inspector/node_inspector.gypi
@@ -15,9 +15,12 @@
'node_protocol_files': [
'<(protocol_tool_path)/lib/Allocator_h.template',
'<(protocol_tool_path)/lib/Array_h.template',
- '<(protocol_tool_path)/lib/Collections_h.template',
+ '<(protocol_tool_path)/lib/base_string_adapter_cc.template',
+ '<(protocol_tool_path)/lib/base_string_adapter_h.template',
'<(protocol_tool_path)/lib/DispatcherBase_cpp.template',
'<(protocol_tool_path)/lib/DispatcherBase_h.template',
+ '<(protocol_tool_path)/lib/encoding_cpp.template',
+ '<(protocol_tool_path)/lib/encoding_h.template',
'<(protocol_tool_path)/lib/ErrorSupport_cpp.template',
'<(protocol_tool_path)/lib/ErrorSupport_h.template',
'<(protocol_tool_path)/lib/Forward_h.template',
diff --git a/src/inspector/node_protocol.pdl b/src/inspector/node_protocol.pdl
index 36d528b937a038..608521b467d9e4 100644
--- a/src/inspector/node_protocol.pdl
+++ b/src/inspector/node_protocol.pdl
@@ -71,6 +71,11 @@ experimental domain NodeWorker
# Detaches from all running workers and disables attaching to new workers as they are started.
command disable
+ # Detached from the worker with given sessionId.
+ command detach
+ parameters
+ SessionID sessionId
+
# Issued when attached to a worker.
event attachedToWorker
parameters
diff --git a/src/inspector/node_string.cc b/src/inspector/node_string.cc
index a79df9e817c049..0d403c66f0197b 100644
--- a/src/inspector/node_string.cc
+++ b/src/inspector/node_string.cc
@@ -107,6 +107,22 @@ String fromUTF8(const uint8_t* data, size_t length) {
return std::string(reinterpret_cast(data), length);
}
+String fromUTF16(const uint16_t* data, size_t length) {
+ icu::UnicodeString utf16(reinterpret_cast(data), length);
+ std::string result;
+ return utf16.toUTF8String(result);
+}
+
+const uint8_t* CharactersUTF8(const String& s) {
+ return reinterpret_cast(s.data());
+}
+
+size_t CharacterCount(const String& s) {
+ icu::UnicodeString utf16 =
+ icu::UnicodeString::fromUTF8(icu::StringPiece(s.data(), s.length()));
+ return utf16.countChar32();
+}
+
} // namespace StringUtil
} // namespace protocol
} // namespace inspector
diff --git a/src/inspector/node_string.h b/src/inspector/node_string.h
index 39545b75aec334..1b8560b6fa5642 100644
--- a/src/inspector/node_string.h
+++ b/src/inspector/node_string.h
@@ -20,16 +20,6 @@ using String = std::string;
using StringBuilder = std::ostringstream;
using ProtocolMessage = std::string;
-class StringUTF8Adapter {
- public:
- explicit StringUTF8Adapter(const std::string& string) : string_(string) { }
- const char* Data() const { return string_.data(); }
- size_t length() const { return string_.length(); }
-
- private:
- const std::string& string_;
-};
-
namespace StringUtil {
// NOLINTNEXTLINE(runtime/references) This is V8 API...
inline void builderAppend(StringBuilder& builder, char c) {
@@ -82,6 +72,13 @@ std::unique_ptr parseMessage(const std::string& message, bool binary);
ProtocolMessage jsonToMessage(String message);
ProtocolMessage binaryToMessage(std::vector message);
String fromUTF8(const uint8_t* data, size_t length);
+String fromUTF16(const uint16_t* data, size_t length);
+const uint8_t* CharactersUTF8(const String& s);
+size_t CharacterCount(const String& s);
+
+// Unimplemented. The generated code will fall back to CharactersUTF8().
+inline uint8_t* CharactersLatin1(const String& s) { return nullptr; }
+inline const uint16_t* CharactersUTF16(const String& s) { return nullptr; }
extern size_t kNotFound;
} // namespace StringUtil
diff --git a/src/inspector/runtime_agent.cc b/src/inspector/runtime_agent.cc
index f8fdbe42d41e03..4056140e703493 100644
--- a/src/inspector/runtime_agent.cc
+++ b/src/inspector/runtime_agent.cc
@@ -16,10 +16,6 @@ void RuntimeAgent::Wire(UberDispatcher* dispatcher) {
}
DispatchResponse RuntimeAgent::notifyWhenWaitingForDisconnect(bool enabled) {
- if (!env_->owns_process_state()) {
- return DispatchResponse::Error(
- "NodeRuntime domain can only be used through main thread sessions");
- }
notify_when_waiting_for_disconnect_ = enabled;
return DispatchResponse::OK();
}
diff --git a/src/inspector/tracing_agent.cc b/src/inspector/tracing_agent.cc
index d87eec6a6469b9..14f55d0cac0ff7 100644
--- a/src/inspector/tracing_agent.cc
+++ b/src/inspector/tracing_agent.cc
@@ -2,9 +2,6 @@
#include "main_thread_interface.h"
#include "node_internals.h"
#include "node_v8_platform-inl.h"
-
-#include "env-inl.h"
-#include "util-inl.h"
#include "v8.h"
#include
@@ -73,7 +70,7 @@ class SendMessageRequest : public Request {
if (frontend_wrapper == nullptr) return;
auto frontend = frontend_wrapper->get();
if (frontend != nullptr) {
- frontend->sendRawNotification(message_);
+ frontend->sendRawJSONNotification(message_);
}
}
diff --git a/src/inspector/worker_agent.cc b/src/inspector/worker_agent.cc
index d343de8494a36f..81706572e646ea 100644
--- a/src/inspector/worker_agent.cc
+++ b/src/inspector/worker_agent.cc
@@ -115,6 +115,11 @@ DispatchResponse WorkerAgent::disable() {
return DispatchResponse::OK();
}
+DispatchResponse WorkerAgent::detach(const String& sessionId) {
+ workers_->Detached(sessionId);
+ return DispatchResponse::OK();
+}
+
void NodeWorkers::WorkerCreated(const std::string& title,
const std::string& url,
bool waiting,
diff --git a/src/inspector/worker_agent.h b/src/inspector/worker_agent.h
index 402c7194163967..1bd25189bf3026 100644
--- a/src/inspector/worker_agent.h
+++ b/src/inspector/worker_agent.h
@@ -25,6 +25,7 @@ class WorkerAgent : public NodeWorker::Backend {
DispatchResponse enable(bool waitForDebuggerOnStart) override;
DispatchResponse disable() override;
+ DispatchResponse detach(const String& sessionId) override;
private:
std::shared_ptr frontend_;
diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc
index d8b5d01a285834..8a12c2dddf7493 100644
--- a/src/inspector_agent.cc
+++ b/src/inspector_agent.cc
@@ -1,5 +1,6 @@
#include "inspector_agent.h"
+#include "env-inl.h"
#include "inspector/main_thread_interface.h"
#include "inspector/node_string.h"
#include "inspector/runtime_agent.h"
@@ -24,6 +25,7 @@
#include // PTHREAD_STACK_MIN
#endif // __POSIX__
+#include
#include
#include
#include
@@ -110,12 +112,18 @@ static int StartDebugSignalHandler() {
CHECK_EQ(0, uv_sem_init(&start_io_thread_semaphore, 0));
pthread_attr_t attr;
CHECK_EQ(0, pthread_attr_init(&attr));
- // Don't shrink the thread's stack on FreeBSD. Said platform decided to
- // follow the pthreads specification to the letter rather than in spirit:
- // https://lists.freebsd.org/pipermail/freebsd-current/2014-March/048885.html
-#ifndef __FreeBSD__
- CHECK_EQ(0, pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN));
-#endif // __FreeBSD__
+#if defined(PTHREAD_STACK_MIN) && !defined(__FreeBSD__)
+ // PTHREAD_STACK_MIN is 2 KB with musl libc, which is too small to safely
+ // receive signals. PTHREAD_STACK_MIN + MINSIGSTKSZ is 8 KB on arm64, which
+ // is the musl architecture with the biggest MINSIGSTKSZ so let's use that
+ // as a lower bound and let's quadruple it just in case. The goal is to avoid
+ // creating a big 2 or 4 MB address space gap (problematic on 32 bits
+ // because of fragmentation), not squeeze out every last byte.
+ // Omitted on FreeBSD because it doesn't seem to like small stacks.
+ const size_t stack_size = std::max(static_cast(4 * 8192),
+ static_cast(PTHREAD_STACK_MIN));
+ CHECK_EQ(0, pthread_attr_setstacksize(&attr, stack_size));
+#endif // defined(PTHREAD_STACK_MIN) && !defined(__FreeBSD__)
CHECK_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED));
sigset_t sigmask;
// Mask all signals.
@@ -464,8 +472,8 @@ class NodeInspectorClient : public V8InspectorClient {
runMessageLoop();
}
- void waitForIoShutdown() {
- waiting_for_io_shutdown_ = true;
+ void waitForSessionsDisconnect() {
+ waiting_for_sessions_disconnect_ = true;
runMessageLoop();
}
@@ -540,6 +548,8 @@ class NodeInspectorClient : public V8InspectorClient {
}
contextDestroyed(env_->context());
}
+ if (waiting_for_sessions_disconnect_ && !is_main_)
+ waiting_for_sessions_disconnect_ = false;
}
void dispatchMessageFromFrontend(int session_id, const StringView& message) {
@@ -670,8 +680,9 @@ class NodeInspectorClient : public V8InspectorClient {
bool shouldRunMessageLoop() {
if (waiting_for_frontend_)
return true;
- if (waiting_for_io_shutdown_ || waiting_for_resume_)
+ if (waiting_for_sessions_disconnect_ || waiting_for_resume_) {
return hasConnectedSessions();
+ }
return false;
}
@@ -715,7 +726,7 @@ class NodeInspectorClient : public V8InspectorClient {
int next_session_id_ = 1;
bool waiting_for_resume_ = false;
bool waiting_for_frontend_ = false;
- bool waiting_for_io_shutdown_ = false;
+ bool waiting_for_sessions_disconnect_ = false;
// Allows accessing Inspector from non-main threads
std::unique_ptr interface_;
std::shared_ptr worker_manager_;
@@ -811,11 +822,14 @@ void Agent::WaitForDisconnect() {
fprintf(stderr, "Waiting for the debugger to disconnect...\n");
fflush(stderr);
}
- if (!client_->notifyWaitingForDisconnect())
+ if (!client_->notifyWaitingForDisconnect()) {
client_->contextDestroyed(parent_env_->context());
+ } else if (is_worker) {
+ client_->waitForSessionsDisconnect();
+ }
if (io_ != nullptr) {
io_->StopAcceptingNewConnections();
- client_->waitForIoShutdown();
+ client_->waitForSessionsDisconnect();
}
}
diff --git a/src/inspector_io.cc b/src/inspector_io.cc
index 7ba19087d01b0d..223e3592a1fc09 100644
--- a/src/inspector_io.cc
+++ b/src/inspector_io.cc
@@ -4,7 +4,6 @@
#include "inspector/main_thread_interface.h"
#include "inspector/node_string.h"
#include "base_object-inl.h"
-#include "env-inl.h"
#include "debug_utils.h"
#include "node.h"
#include "node_crypto.h"
diff --git a/src/inspector_js_api.cc b/src/inspector_js_api.cc
index 5caf3fa09a4d10..9d649385706131 100644
--- a/src/inspector_js_api.cc
+++ b/src/inspector_js_api.cc
@@ -1,6 +1,7 @@
#include "base_object-inl.h"
#include "inspector_agent.h"
#include "inspector_io.h"
+#include "memory_tracker-inl.h"
#include "util-inl.h"
#include "v8.h"
#include "v8-inspector.h"
diff --git a/src/inspector_profiler.cc b/src/inspector_profiler.cc
index 4604e0a5b441e1..1b20398dba4d3d 100644
--- a/src/inspector_profiler.cc
+++ b/src/inspector_profiler.cc
@@ -2,6 +2,8 @@
#include
#include "base_object-inl.h"
#include "debug_utils.h"
+#include "diagnosticfilename-inl.h"
+#include "memory_tracker-inl.h"
#include "node_file.h"
#include "node_internals.h"
#include "v8-inspector.h"
@@ -256,6 +258,44 @@ void V8CpuProfilerConnection::End() {
DispatchMessage("Profiler.stop");
}
+std::string V8HeapProfilerConnection::GetDirectory() const {
+ return env()->heap_prof_dir();
+}
+
+std::string V8HeapProfilerConnection::GetFilename() const {
+ return env()->heap_prof_name();
+}
+
+MaybeLocal