diff --git a/addons/c_addons.md b/addons/c_addons.md
index e69550b8..986a998c 100644
--- a/addons/c_addons.md
+++ b/addons/c_addons.md
@@ -26,7 +26,7 @@
- Node.js 包含了其他的静态链接库,如 OpenSSL。
这些库位于 Node.js 源代码树中的 `deps/` 目录。
只有 libuv、OpenSSL、V8 和 zlib 符号是被 Node.js 有目的地重新公开,并且可以被插件在不同程度上使用。
- 更多信息可查看[链接到 Node.js 自有的依赖项][Linking to Node.js' own dependencies]。
+ 更多信息可查看[链接到 Node.js 自带的库][Linking to libraries included with Node.js]。
以下所有示例均可供[下载][download],并可用作学习插件的起点。
diff --git a/addons/linking_to_node_js_own_dependencies.md b/addons/linking_to_libraries_included_with_node_js.md
similarity index 100%
rename from addons/linking_to_node_js_own_dependencies.md
rename to addons/linking_to_libraries_included_with_node_js.md
diff --git a/assert/assert.md b/assert/assert.md
index d235a8ab..cdfe6454 100644
--- a/assert/assert.md
+++ b/assert/assert.md
@@ -4,5 +4,4 @@
> 稳定性: 2 - 稳定
`assert` 模块提供了一组简单的断言测试,可用于测试不变量。
-该模块提供了建议的[严格模式][`strict` mode]和更宽松的遗留模式。
diff --git a/assert/assert_deepequal_actual_expected_message.md b/assert/assert_deepequal_actual_expected_message.md
index 830d57b2..be560bea 100644
--- a/assert/assert_deepequal_actual_expected_message.md
+++ b/assert/assert_deepequal_actual_expected_message.md
@@ -26,18 +26,18 @@ changes:
* `expected` {any}
* `message` {string|Error}
-**Strict mode**
+**Strict assertion mode**
An alias of [`assert.deepStrictEqual()`][].
-**Legacy mode**
+**Legacy assertion mode**
> Stability: 0 - Deprecated: Use [`assert.deepStrictEqual()`][] instead.
Tests for deep equality between the `actual` and `expected` parameters. Consider
using [`assert.deepStrictEqual()`][] instead. [`assert.deepEqual()`][] can have
-potentially surprising results.
+surprising results.
-"Deep" equality means that the enumerable "own" properties of child objects
+_Deep equality_ means that the enumerable "own" properties of child objects
are also recursively evaluated by the following rules.
diff --git a/assert/assert_equal_actual_expected_message.md b/assert/assert_equal_actual_expected_message.md
index 61b4458f..4389d04b 100644
--- a/assert/assert_equal_actual_expected_message.md
+++ b/assert/assert_equal_actual_expected_message.md
@@ -6,11 +6,11 @@ added: v0.1.21
* `expected` {any}
* `message` {string|Error}
-**Strict mode**
+**Strict assertion mode**
An alias of [`assert.strictEqual()`][].
-**Legacy mode**
+**Legacy assertion mode**
> Stability: 0 - Deprecated: Use [`assert.strictEqual()`][] instead.
diff --git a/assert/assert_notdeepequal_actual_expected_message.md b/assert/assert_notdeepequal_actual_expected_message.md
index 50ae36ed..17649f43 100644
--- a/assert/assert_notdeepequal_actual_expected_message.md
+++ b/assert/assert_notdeepequal_actual_expected_message.md
@@ -22,11 +22,11 @@ changes:
* `expected` {any}
* `message` {string|Error}
-**Strict mode**
+**Strict assertion mode**
An alias of [`assert.notDeepStrictEqual()`][].
-**Legacy mode**
+**Legacy assertion mode**
> Stability: 0 - Deprecated: Use [`assert.notDeepStrictEqual()`][] instead.
diff --git a/assert/assert_notequal_actual_expected_message.md b/assert/assert_notequal_actual_expected_message.md
index a970ada0..b206bd5e 100644
--- a/assert/assert_notequal_actual_expected_message.md
+++ b/assert/assert_notequal_actual_expected_message.md
@@ -6,11 +6,11 @@ added: v0.1.21
* `expected` {any}
* `message` {string|Error}
-**Strict mode**
+**Strict assertion mode**
An alias of [`assert.notStrictEqual()`][].
-**Legacy mode**
+**Legacy assertion mode**
> Stability: 0 - Deprecated: Use [`assert.notStrictEqual()`][] instead.
diff --git a/assert/assert_rejects_asyncfn_error_message.md b/assert/assert_rejects_asyncfn_error_message.md
index 1433eddd..0840e658 100644
--- a/assert/assert_rejects_asyncfn_error_message.md
+++ b/assert/assert_rejects_asyncfn_error_message.md
@@ -32,6 +32,21 @@ added: v10.0.0
})();
```
+```js
+(async () => {
+ await assert.rejects(
+ async () => {
+ throw new TypeError('错误值');
+ },
+ (err) => {
+ assert.strictEqual(err.name, 'TypeError');
+ assert.strictEqual(err.message, '错误值');
+ return true;
+ }
+ );
+})();
+```
+
```js
assert.rejects(
Promise.reject(new Error('错误值')),
diff --git a/assert/legacy_mode.md b/assert/legacy_assertion_mode.md
similarity index 66%
rename from assert/legacy_mode.md
rename to assert/legacy_assertion_mode.md
index 7e1e1d35..f2194de1 100644
--- a/assert/legacy_mode.md
+++ b/assert/legacy_assertion_mode.md
@@ -1,19 +1,19 @@
-遗留模式在以下方法中使用[抽象的相等性比较][Abstract Equality Comparison]:
+遗留的断言模式在以下方法中使用[抽象的相等性比较][Abstract Equality Comparison]:
* [`assert.deepEqual()`][]
* [`assert.equal()`][]
* [`assert.notDeepEqual()`][]
* [`assert.notEqual()`][]
-使用遗留模式:
+使用遗留的断言模式:
```js
const assert = require('assert');
```
-只要有可能,请使用[严格模式][`strict` mode]。
+只要有可能,请使用[严格的断言模式][strict assertion mode]。
否则,[抽象的相等性比较][Abstract Equality Comparison]可能会导致意外的结果。
特别是对于 [`assert.deepEqual()`],其中的比较规则是松散的:
diff --git a/assert/strict_mode.md b/assert/strict_assertion_mode.md
similarity index 55%
rename from assert/strict_mode.md
rename to assert/strict_assertion_mode.md
index 3f757a63..cd5fd09a 100644
--- a/assert/strict_mode.md
+++ b/assert/strict_assertion_mode.md
@@ -1,21 +1,25 @@
-在严格模式中(不要与 `"use strict"` 混淆),任何 `assert` 函数都将使用严格函数模式中使用的相等性。
+在严格的断言模式中,非严格的方法与它们对应的严格方法的行为是一样的。
例如,[`assert.deepEqual()`] 将与 [`assert.deepStrictEqual()`] 一样效果。
-在严格模式中,对象的错误消息会显示差异。
-在遗留模式下,对象的错误消息会显示对象,通常是截断的。
+在严格的断言模式中,对象的错误消息会显示差异。
+在遗留的断言模式下,对象的错误消息会显示对象,通常是截断的。
-使用严格模式:
+使用严格的断言模式:
```js
const assert = require('assert').strict;
@@ -43,7 +47,6 @@ assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]);
```
要停用颜色,则使用 `NO_COLOR` 或 `NODE_DISABLE_COLORS` 环境变量。
-注意,这也将停用 REPL 中的颜色。
-
+这也将停用 REPL 中的颜色。
有关终端环境中颜色支持的更多信息,参阅 [getColorDepth()][_tty_writestream_getcolordepth] 文档。
diff --git a/async_hooks/async_hooks.md b/async_hooks/async_hooks.md
index dc84973c..591788ba 100644
--- a/async_hooks/async_hooks.md
+++ b/async_hooks/async_hooks.md
@@ -3,9 +3,8 @@
> Stability: 1 - Experimental
-The `async_hooks` module provides an API to register callbacks tracking the
-lifetime of asynchronous resources created inside a Node.js application.
-It can be accessed using:
+The `async_hooks` module provides an API to track asynchronous resources. It
+can be accessed using:
```js
const async_hooks = require('async_hooks');
diff --git a/async_hooks/asynchronous_context_example.md b/async_hooks/asynchronous_context_example.md
index 879fcced..52a31466 100644
--- a/async_hooks/asynchronous_context_example.md
+++ b/async_hooks/asynchronous_context_example.md
@@ -70,8 +70,8 @@ Timeout(7) -> TickObject(6) -> root(1)
```
The `TCPSERVERWRAP` is not part of this graph, even though it was the reason for
-`console.log()` being called. This is because binding to a port without a
-hostname is a *synchronous* operation, but to maintain a completely asynchronous
+`console.log()` being called. This is because binding to a port without a host
+name is a *synchronous* operation, but to maintain a completely asynchronous
API the user's callback is placed in a `process.nextTick()`.
The graph only shows *when* a resource was created, not *why*, so to track
diff --git a/async_hooks/asyncresource_triggerasyncid.md b/async_hooks/asyncresource_triggerasyncid.md
index b6cd2e94..01592e33 100644
--- a/async_hooks/asyncresource_triggerasyncid.md
+++ b/async_hooks/asyncresource_triggerasyncid.md
@@ -2,12 +2,4 @@
* Returns: {number} The same `triggerAsyncId` that is passed to the
`AsyncResource` constructor.
-
-
-
-
-
-
-
-
-
+
diff --git a/async_hooks/resource.md b/async_hooks/resource.md
index 40773705..7ef4854a 100644
--- a/async_hooks/resource.md
+++ b/async_hooks/resource.md
@@ -2,7 +2,7 @@
`resource` is an object that represents the actual async resource that has
been initialized. This can contain useful information that can vary based on
the value of `type`. For instance, for the `GETADDRINFOREQWRAP` resource type,
-`resource` provides the hostname used when looking up the IP address for the
+`resource` provides the host name used when looking up the IP address for the
host in `net.Server.listen()`. The API for accessing this information is
currently not considered public, but using the Embedder API, users can provide
and document their own resource objects. For example, such a resource object
diff --git a/async_hooks/using_asyncresource_for_a_worker_thread_pool.md b/async_hooks/using_asyncresource_for_a_worker_thread_pool.md
new file mode 100644
index 00000000..d1ba9033
--- /dev/null
+++ b/async_hooks/using_asyncresource_for_a_worker_thread_pool.md
@@ -0,0 +1,129 @@
+
+The following example shows how to use the `AsyncResource` class to properly
+provide async tracking for a [`Worker`][] pool. Other resource pools, such as
+database connection pools, can follow a similar model.
+
+Assuming that the task is adding two numbers, using a file named
+`task_processor.js` with the following content:
+
+```js
+const { parentPort } = require('worker_threads');
+parentPort.on('message', (task) => {
+ parentPort.postMessage(task.a + task.b);
+});
+```
+
+a Worker pool around it could use the following structure:
+
+```js
+const { AsyncResource } = require('async_hooks');
+const { EventEmitter } = require('events');
+const path = require('path');
+const { Worker } = require('worker_threads');
+
+const kTaskInfo = Symbol('kTaskInfo');
+const kWorkerFreedEvent = Symbol('kWorkerFreedEvent');
+
+class WorkerPoolTaskInfo extends AsyncResource {
+ constructor(callback) {
+ super('WorkerPoolTaskInfo');
+ this.callback = callback;
+ }
+
+ done(err, result) {
+ this.runInAsyncScope(this.callback, null, err, result);
+ this.emitDestroy(); // `TaskInfo`s are used only once.
+ }
+}
+
+class WorkerPool extends EventEmitter {
+ constructor(numThreads) {
+ super();
+ this.numThreads = numThreads;
+ this.workers = [];
+ this.freeWorkers = [];
+
+ for (let i = 0; i < numThreads; i++)
+ this.addNewWorker();
+ }
+
+ addNewWorker() {
+ const worker = new Worker(path.resolve(__dirname, 'task_processor.js'));
+ worker.on('message', (result) => {
+ // In case of success: Call the callback that was passed to `runTask`,
+ // remove the `TaskInfo` associated with the Worker, and mark it as free
+ // again.
+ worker[kTaskInfo].done(null, result);
+ worker[kTaskInfo] = null;
+ this.freeWorkers.push(worker);
+ this.emit(kWorkerFreedEvent);
+ });
+ worker.on('error', (err) => {
+ // In case of an uncaught exception: Call the callback that was passed to
+ // `runTask` with the error.
+ if (worker[kTaskInfo])
+ worker[kTaskInfo].done(err, null);
+ else
+ this.emit('error', err);
+ // Remove the worker from the list and start a new Worker to replace the
+ // current one.
+ this.workers.splice(this.workers.indexOf(worker), 1);
+ this.addNewWorker();
+ });
+ this.workers.push(worker);
+ this.freeWorkers.push(worker);
+ }
+
+ runTask(task, callback) {
+ if (this.freeWorkers.length === 0) {
+ // No free threads, wait until a worker thread becomes free.
+ this.once(kWorkerFreedEvent, () => this.runTask(task, callback));
+ return;
+ }
+
+ const worker = this.freeWorkers.pop();
+ worker[kTaskInfo] = new WorkerPoolTaskInfo(callback);
+ worker.postMessage(task);
+ }
+
+ close() {
+ for (const worker of this.workers) worker.terminate();
+ }
+}
+
+module.exports = WorkerPool;
+```
+
+Without the explicit tracking added by the `WorkerPoolTaskInfo` objects,
+it would appear that the callbacks are associated with the individual `Worker`
+objects. However, the creation of the `Worker`s is not associated with the
+creation of the tasks and does not provide information about when tasks
+were scheduled.
+
+This pool could be used as follows:
+
+```js
+const WorkerPool = require('./worker_pool.js');
+const os = require('os');
+
+const pool = new WorkerPool(os.cpus().length);
+
+let finished = 0;
+for (let i = 0; i < 10; i++) {
+ pool.runTask({ a: 42, b: 100 }, (err, result) => {
+ console.log(i, err, result);
+ if (++finished === 10)
+ pool.close();
+ });
+}
+```
+
+
+
+
+
+
+
+
+
+
diff --git a/buffer/buffers_and_character_encodings.md b/buffer/buffers_and_character_encodings.md
index dbfc93b6..55b963e8 100644
--- a/buffer/buffers_and_character_encodings.md
+++ b/buffer/buffers_and_character_encodings.md
@@ -42,6 +42,17 @@ Node.js 当前支持的字符编码有:
* `'hex'`: 将每个字节编码成两个十六进制的字符。
+```js
+Buffer.from('1ag', 'hex');
+// 打印 ,当遇到第一个非十六进制的值('g')时,则数据会被截断。
+
+Buffer.from('1a7g', 'hex');
+// 打印 ,当数据以一个数字('7')结尾时,则数据会被截断。
+
+Buffer.from('1634', 'hex');
+// 打印 ,所有数据均可用。
+```
+
现代的 Web 浏览器遵循 [WHATWG 编码标准][WHATWG Encoding Standard],将 `'latin1'` 和 `'ISO-8859-1'` 别名为 `'win-1252'`。
这意味着当执行 `http.get()` 之类的操作时,如果返回的字符集是 WHATWG 规范中列出的字符集之一,则服务器可能实际返回 `'win-1252'` 编码的数据,而使用 `'latin1'` 编码可能错误地解码字符。
diff --git a/buffer/class_method_buffer_from_arraybuffer_byteoffset_length.md b/buffer/class_method_buffer_from_arraybuffer_byteoffset_length.md
index fc766596..3cf11e5c 100644
--- a/buffer/class_method_buffer_from_arraybuffer_byteoffset_length.md
+++ b/buffer/class_method_buffer_from_arraybuffer_byteoffset_length.md
@@ -4,7 +4,7 @@ added: v5.10.0
* `arrayBuffer` {ArrayBuffer|SharedArrayBuffer} 一个 [`ArrayBuffer`]、[`SharedArrayBuffer`]、或 [`TypedArray`] 的 `.buffer` 属性。
* `byteOffset` {integer} 开始拷贝的索引。**默认值:** `0`。
-* `length` {integer} 拷贝的字节数。**默认值:** `arrayBuffer.length - byteOffset`。
+* `length` {integer} 拷贝的字节数。**默认值:** `arrayBuffer.byteLength - byteOffset`。
创建 [`ArrayBuffer`] 的视图,但不会拷贝底层内存。
例如,当传入 [`TypedArray`] 的 `.buffer` 属性的引用时,新建的 `Buffer` 会与 [`TypedArray`] 共享同一内存。
diff --git a/buffer/new_buffer_arraybuffer_byteoffset_length.md b/buffer/new_buffer_arraybuffer_byteoffset_length.md
index 1e2e4726..2e71b3ce 100644
--- a/buffer/new_buffer_arraybuffer_byteoffset_length.md
+++ b/buffer/new_buffer_arraybuffer_byteoffset_length.md
@@ -25,7 +25,7 @@ changes:
[`SharedArrayBuffer`][] or the `.buffer` property of a [`TypedArray`][].
* `byteOffset` {integer} Index of first byte to expose. **Default:** `0`.
* `length` {integer} Number of bytes to expose.
- **Default:** `arrayBuffer.length - byteOffset`.
+ **Default:** `arrayBuffer.byteLength - byteOffset`.
This creates a view of the [`ArrayBuffer`][] or [`SharedArrayBuffer`][] without
copying the underlying memory. For example, when passed a reference to the
diff --git a/buffer/the_zero_fill_buffers_command_line_option.md b/buffer/the_zero_fill_buffers_command_line_option.md
index e814f500..beced024 100644
--- a/buffer/the_zero_fill_buffers_command_line_option.md
+++ b/buffer/the_zero_fill_buffers_command_line_option.md
@@ -3,10 +3,9 @@ added: v5.10.0
-->
可以使用 `--zero-fill-buffers` 命令行选项启动 Node.js,以使所有新分配的 `Buffer` 实例在创建时默认使用零来填充。
-在 Node.js 8.0.0 之前,这包括 `new Buffer(size)`、[`Buffer.allocUnsafe()`]、[`Buffer.allocUnsafeSlow()`] 和 `new SlowBuffer(size)` 分配的 buffer。
-从 Node.js 8.0.0 开始,无论是否使用此选项,使用 `new` 分配的 buffer 始终用零填充。
+如果没有该选项,则使用 [`Buffer.allocUnsafe()`]、[`Buffer.allocUnsafeSlow()`] 和 `new SlowBuffer(size)` 创建的 buffer 不会填充零。
使用这个选项可能会对性能产生重大的负面影响。
-建议仅在需要强制新分配的 `Buffer` 实例不能包含可能敏感的旧数据时,才使用 `--zero-fill-buffers` 选项。
+仅在需要强制新分配的 `Buffer` 实例不能包含可能敏感的旧数据时,才使用 `--zero-fill-buffers` 选项。
```console
$ node --zero-fill-buffers
diff --git a/child_process/event_exit.md b/child_process/event_exit.md
index ceb36676..dcaf3609 100644
--- a/child_process/event_exit.md
+++ b/child_process/event_exit.md
@@ -8,7 +8,7 @@ added: v0.1.90
当子进程结束后时会触发 `'exit'` 事件。
如果进程退出,则 `code` 是进程的最终退出码,否则为 `null`。
如果进程是因为收到的信号而终止,则 `signal` 是信号的字符串名称,否则为 `null`。
-这两个值至少有一个是非空的。
+这两个值至少有一个是非 `null` 的。
当 `'exit'` 事件被触发时,子进程的 stdio 流可能依然是打开的。
diff --git a/child_process/subprocess_exitcode.md b/child_process/subprocess_exitcode.md
new file mode 100644
index 00000000..916d838d
--- /dev/null
+++ b/child_process/subprocess_exitcode.md
@@ -0,0 +1,6 @@
+
+* {integer}
+
+The `subprocess.exitCode` property indicates the exit code of the child process.
+If the child process is still running, the field will be `null`.
+
diff --git a/child_process/subprocess_signalcode.md b/child_process/subprocess_signalcode.md
new file mode 100644
index 00000000..08433eff
--- /dev/null
+++ b/child_process/subprocess_signalcode.md
@@ -0,0 +1,6 @@
+
+* {integer}
+
+The `subprocess.signalCode` property indicates the signal number received by
+the child process if any, else `null`.
+
diff --git a/child_process/subprocess_spawnargs.md b/child_process/subprocess_spawnargs.md
new file mode 100644
index 00000000..6cd80641
--- /dev/null
+++ b/child_process/subprocess_spawnargs.md
@@ -0,0 +1,6 @@
+
+* {Array}
+
+The `subprocess.spawnargs` property represents the full list of command line
+arguments the child process was launched with.
+
diff --git a/child_process/subprocess_spawnfile.md b/child_process/subprocess_spawnfile.md
new file mode 100644
index 00000000..082a0ba2
--- /dev/null
+++ b/child_process/subprocess_spawnfile.md
@@ -0,0 +1,13 @@
+
+* {string}
+
+The `subprocess.spawnfile` property indicates the executable file name of
+the child process that is launched.
+
+For [`child_process.fork()`][], its value will be equal to
+[`process.execPath`][].
+For [`child_process.spawn()`][], its value will be the name of
+the executable file.
+For [`child_process.exec()`][], its value will be the name of the shell
+in which the child process is launched.
+
diff --git a/cli/abort_on_uncaught_exception.md b/cli/abort_on_uncaught_exception.md
index d6365c27..d5248d99 100644
--- a/cli/abort_on_uncaught_exception.md
+++ b/cli/abort_on_uncaught_exception.md
@@ -1,5 +1,5 @@
Aborting instead of exiting causes a core file to be generated for post-mortem
diff --git a/cli/experimental_import_meta_resolve.md b/cli/experimental_import_meta_resolve.md
new file mode 100644
index 00000000..06a2ba9d
--- /dev/null
+++ b/cli/experimental_import_meta_resolve.md
@@ -0,0 +1,6 @@
+
+
+Enable experimental `import.meta.resolve()` support.
+
diff --git a/cli/jitless.md b/cli/jitless.md
new file mode 100644
index 00000000..d1e6caf4
--- /dev/null
+++ b/cli/jitless.md
@@ -0,0 +1,11 @@
+
+
+Disable [runtime allocation of executable memory][jitless]. This may be
+required on some platforms for security reasons. It can also reduce attack
+surface on other platforms, but the performance impact may be severe.
+
+This flag is inherited from V8 and is subject to change upstream. It may
+disappear in a non-semver-major release.
+
diff --git a/cli/node_options_options.md b/cli/node_options_options.md
index 336cde99..66c62e9a 100644
--- a/cli/node_options_options.md
+++ b/cli/node_options_options.md
@@ -37,6 +37,7 @@ Node.js options that are allowed are:
* `--enable-fips`
* `--enable-source-maps`
+* `--experimental-import-meta-resolve`
* `--experimental-json-modules`
* `--experimental-loader`
* `--experimental-modules`
@@ -111,6 +112,7 @@ V8 options that are allowed are:
* `--abort-on-uncaught-exception`
* `--disallow-code-generation-from-strings`
* `--interpreted-frames-native-stack`
+* `--jitless`
* `--max-old-space-size`
* `--perf-basic-prof-only-functions`
* `--perf-basic-prof`
@@ -119,3 +121,6 @@ V8 options that are allowed are:
* `--stack-trace-limit`
+`--perf-basic-prof-only-functions`, `--perf-basic-prof`,
+`--perf-prof-unwinding-info`, and `--perf-prof` are only available on Linux.
+
diff --git a/cli/uv_threadpool_size_size.md b/cli/uv_threadpool_size_size.md
index ee336b2d..e6c0bc55 100644
--- a/cli/uv_threadpool_size_size.md
+++ b/cli/uv_threadpool_size_size.md
@@ -39,5 +39,6 @@ greater than `4` (its current default value). For more information, see the
+
diff --git a/crypto/class_sign.md b/crypto/class_sign.md
index 08952469..15b0a235 100644
--- a/crypto/class_sign.md
+++ b/crypto/class_sign.md
@@ -31,8 +31,8 @@ const signature = sign.sign(privateKey, 'hex');
const verify = crypto.createVerify('SHA256');
verify.write('要生成签名的数据');
verify.end();
-console.log(verify.verify(publicKey, signature));
-// 打印 true 或 false。
+console.log(verify.verify(publicKey, signature, 'hex'));
+// 打印 true
```
示例,使用 [`sign.update()`] 和 [`verify.update()`] 方法:
diff --git a/crypto/crypto_privatedecrypt_privatekey_buffer.md b/crypto/crypto_privatedecrypt_privatekey_buffer.md
index f91d3202..91a69a63 100644
--- a/crypto/crypto_privatedecrypt_privatekey_buffer.md
+++ b/crypto/crypto_privatedecrypt_privatekey_buffer.md
@@ -15,6 +15,8 @@ changes:
* `privateKey` {Object | string | Buffer | KeyObject}
* `oaepHash` {string} The hash function to use for OAEP padding.
**Default:** `'sha1'`
+ * `oaepLabel` {Buffer | TypedArray | DataView} The label to use for OAEP
+ padding. If not specified, no label is used.
* `padding` {crypto.constants} An optional padding value defined in
`crypto.constants`, which may be: `crypto.constants.RSA_NO_PADDING`,
`crypto.constants.RSA_PKCS1_PADDING`, or
diff --git a/crypto/crypto_publicencrypt_key_buffer.md b/crypto/crypto_publicencrypt_key_buffer.md
index f771256f..5168fa3e 100644
--- a/crypto/crypto_publicencrypt_key_buffer.md
+++ b/crypto/crypto_publicencrypt_key_buffer.md
@@ -16,6 +16,8 @@ changes:
* `key` {string | Buffer | KeyObject} A PEM encoded public or private key.
* `oaepHash` {string} The hash function to use for OAEP padding.
**Default:** `'sha1'`
+ * `oaepLabel` {Buffer | TypedArray | DataView} The label to use for OAEP
+ padding. If not specified, no label is used.
* `passphrase` {string | Buffer} An optional passphrase for the private key.
* `padding` {crypto.constants} An optional padding value defined in
`crypto.constants`, which may be: `crypto.constants.RSA_NO_PADDING`,
diff --git a/deprecations/dep0118_dns_lookup_support_for_a_falsy_host_name.md b/deprecations/dep0118_dns_lookup_support_for_a_falsy_host_name.md
new file mode 100644
index 00000000..4bbba609
--- /dev/null
+++ b/deprecations/dep0118_dns_lookup_support_for_a_falsy_host_name.md
@@ -0,0 +1,15 @@
+
+
+Type: Runtime
+
+Previous versions of Node.js supported `dns.lookup()` with a falsy host name
+like `dns.lookup(false)` due to backward compatibility.
+This behavior is undocumented and is thought to be unused in real world apps.
+It will become an error in future versions of Node.js.
+
+
diff --git a/errors/common_system_errors.md b/errors/common_system_errors.md
index 3c633a06..77b682d0 100644
--- a/errors/common_system_errors.md
+++ b/errors/common_system_errors.md
@@ -21,13 +21,12 @@
当一次并行打开多个文件时会发生这个错误,尤其是在进程的文件描述限制数量较低的操作系统(如 macOS)。
要解决这个限制,可在运行 Node.js 进程的同一 shell 中运行 `ulimit -n 2048`。
-- `ENOENT` (无此文件或目录): 通常是由 [`fs`] 操作引起的,表明指定的路径不存在,即给定的路径找不到文件或目录。
+- `ENOENT` (无此文件或目录): 通常是由 [`fs`] 操作引起的,表明指定的路径不存在。给定的路径找不到文件或目录。
- `ENOTDIR` (不是一个目录): 给定的路径虽然存在,但不是一个目录。
通常是由 [`fs.readdir`] 引起的。
-- `ENOTEMPTY` (目录非空): 一个操作的目标是一个非空的目录,而要求的是一个空目录。
- 通常是由 [`fs.unlink`] 引起的。
+- `ENOTEMPTY` (目录非空): 一个操作的目标是一个非空的目录,而要求的是一个空目录,通常是由 [`fs.unlink`] 引起的。
- `ENOTFOUND` (DNS查找失败): 表示 `EAI_NODATA` 或 `EAI_NONAME` 的 DNS 失败。 这不是标准的 POSIX 错误。
diff --git a/errors/err_incompatible_option_pair.md b/errors/err_incompatible_option_pair.md
index 3e8b1b7e..33b64a4a 100644
--- a/errors/err_incompatible_option_pair.md
+++ b/errors/err_incompatible_option_pair.md
@@ -1,5 +1,5 @@
-An option pair is incompatible with each other and can not be used at the same
+An option pair is incompatible with each other and cannot be used at the same
time.
diff --git a/errors/err_invalid_ip_address.md b/errors/err_invalid_ip_address.md
index 6b58bf9e..08bff1d6 100644
--- a/errors/err_invalid_ip_address.md
+++ b/errors/err_invalid_ip_address.md
@@ -1,4 +1,4 @@
An IP address is not valid.
-
+
diff --git a/errors/err_invalid_module_specifier.md b/errors/err_invalid_module_specifier.md
new file mode 100644
index 00000000..f15db3b6
--- /dev/null
+++ b/errors/err_invalid_module_specifier.md
@@ -0,0 +1,5 @@
+
+The imported module string is an invalid URL, package name, or package subpath
+specifier.
+
+
diff --git a/errors/err_invalid_package_config.md b/errors/err_invalid_package_config.md
index 8499fac0..571aebf4 100644
--- a/errors/err_invalid_package_config.md
+++ b/errors/err_invalid_package_config.md
@@ -1,4 +1,4 @@
An invalid `package.json` file was found which failed parsing.
-
+
diff --git a/errors/err_invalid_package_target.md b/errors/err_invalid_package_target.md
new file mode 100644
index 00000000..512474c9
--- /dev/null
+++ b/errors/err_invalid_package_target.md
@@ -0,0 +1,5 @@
+
+The `package.json` [exports][] field contains an invalid target mapping value
+for the attempted module resolution.
+
+
diff --git a/errors/err_out_of_range.md b/errors/err_out_of_range.md
index 2088c2cf..a8976b01 100644
--- a/errors/err_out_of_range.md
+++ b/errors/err_out_of_range.md
@@ -1,4 +1,4 @@
A given value is out of the accepted range.
-
+
diff --git a/errors/err_package_path_not_exported.md b/errors/err_package_path_not_exported.md
new file mode 100644
index 00000000..45e7f53e
--- /dev/null
+++ b/errors/err_package_path_not_exported.md
@@ -0,0 +1,6 @@
+
+The `package.json` [exports][] field does not export the requested subpath.
+Because exports are encapsulated, private internal modules that are not exported
+cannot be imported through the package resolution, unless using an absolute URL.
+
+
diff --git a/errors/err_tls_cert_altname_invalid.md b/errors/err_tls_cert_altname_invalid.md
index 15e7e075..520f1b03 100644
--- a/errors/err_tls_cert_altname_invalid.md
+++ b/errors/err_tls_cert_altname_invalid.md
@@ -1,5 +1,5 @@
-While using TLS, the hostname/IP of the peer did not match any of the
+While using TLS, the host name/IP of the peer did not match any of the
`subjectAltNames` in its certificate.
diff --git a/errors/err_tls_required_server_name.md b/errors/err_tls_required_server_name.md
index 07848a81..a561427d 100644
--- a/errors/err_tls_required_server_name.md
+++ b/errors/err_tls_required_server_name.md
@@ -1,5 +1,5 @@
While using TLS, the `server.addContext()` method was called without providing
-a hostname in the first parameter.
+a host name in the first parameter.
diff --git a/errors/err_tty_writable_not_readable.md b/errors/err_tty_writable_not_readable.md
index f565a826..a9b8591b 100644
--- a/errors/err_tty_writable_not_readable.md
+++ b/errors/err_tty_writable_not_readable.md
@@ -63,5 +63,6 @@ such as `process.stdout.on('data')`.
+
diff --git a/errors/err_wasi_already_started.md b/errors/err_wasi_already_started.md
index c88243fe..b0801fec 100644
--- a/errors/err_wasi_already_started.md
+++ b/errors/err_wasi_already_started.md
@@ -1,4 +1,4 @@
The WASI instance has already started.
-
+
diff --git a/errors/err_worker_init_failed.md b/errors/err_worker_init_failed.md
new file mode 100644
index 00000000..ae9ae4b5
--- /dev/null
+++ b/errors/err_worker_init_failed.md
@@ -0,0 +1,4 @@
+
+The `Worker` initialization failed.
+
+
diff --git a/esm/approach_1_use_an_es_module_wrapper.md b/esm/approach_1_use_an_es_module_wrapper.md
index 14800c09..d5309509 100644
--- a/esm/approach_1_use_an_es_module_wrapper.md
+++ b/esm/approach_1_use_an_es_module_wrapper.md
@@ -11,8 +11,8 @@ CommonJS entry point for `require`.
"type": "module",
"main": "./index.cjs",
"exports": {
- "require": "./index.cjs",
- "import": "./wrapper.mjs"
+ "import": "./wrapper.mjs",
+ "require": "./index.cjs"
}
}
```
diff --git a/esm/approach_2_isolate_state.md b/esm/approach_2_isolate_state.md
index 4dbb3add..9c491e27 100644
--- a/esm/approach_2_isolate_state.md
+++ b/esm/approach_2_isolate_state.md
@@ -1,6 +1,6 @@
-The most straightforward `package.json` would be one that defines the separate
-CommonJS and ES module entry points directly:
+A `package.json` file can define the separate CommonJS and ES module entry
+points directly:
```js
diff --git a/esm/code_getglobalpreloadcode_code_hook.md b/esm/code_getglobalpreloadcode_code_hook.md
new file mode 100644
index 00000000..c65c4926
--- /dev/null
+++ b/esm/code_getglobalpreloadcode_code_hook.md
@@ -0,0 +1,32 @@
+
+> Note: The loaders API is being redesigned. This hook may disappear or its
+> signature may change. Do not rely on the API described below.
+
+Sometimes it can be necessary to run some code inside of the same global scope
+that the application will run in. This hook allows to return a string that will
+be ran as sloppy-mode script on startup.
+
+Similar to how CommonJS wrappers work, the code runs in an implicit function
+scope. The only argument is a `require`-like function that can be used to load
+builtins like "fs": `getBuiltin(request: string)`.
+
+If the code needs more advanced `require` features, it will have to construct
+its own `require` using `module.createRequire()`.
+
+```js
+/**
+ * @returns {string} Code to run before application startup
+ */
+export function getGlobalPreloadCode() {
+ return `\
+globalThis.someInjectedProperty = 42;
+console.log('I just set some globals!');
+
+const { createRequire } = getBuiltin('module');
+
+const require = createRequire(process.cwd + '/');
+// [...]
+`;
+}
+```
+
diff --git a/esm/code_package_json_code_code_main_code.md b/esm/code_package_json_code_code_main_code.md
deleted file mode 100644
index 4587284b..00000000
--- a/esm/code_package_json_code_code_main_code.md
+++ /dev/null
@@ -1,36 +0,0 @@
-
-The `package.json` `"main"` field defines the entry point for a package,
-whether the package is included into CommonJS via `require` or into an ES
-module via `import`.
-
-
-```js
-// ./node_modules/es-module-package/package.json
-{
- "type": "module",
- "main": "./src/index.js"
-}
-```
-
-```js
-// ./my-app.mjs
-
-import { something } from 'es-module-package';
-// Loads from ./node_modules/es-module-package/src/index.js
-```
-
-An attempt to `require` the above `es-module-package` would attempt to load
-`./node_modules/es-module-package/src/index.js` as CommonJS, which would throw
-an error as Node.js would not be able to parse the `export` statement in
-CommonJS.
-
-As with `import` statements, for ES module usage the value of `"main"` must be
-a full path including extension: `"./index.mjs"`, not `"./index"`.
-
-If the `package.json` `"type"` field is omitted, a `.js` file in `"main"` will
-be interpreted as CommonJS.
-
-The `"main"` field can point to exactly one file, regardless of whether the
-package is referenced via `require` (in a CommonJS context) or `import` (in an
-ES module context).
-
diff --git a/esm/conditional_exports.md b/esm/conditional_exports.md
index 9d2617e5..4dc5d563 100644
--- a/esm/conditional_exports.md
+++ b/esm/conditional_exports.md
@@ -3,47 +3,64 @@ Conditional exports provide a way to map to different paths depending on
certain conditions. They are supported for both CommonJS and ES module imports.
For example, a package that wants to provide different ES module exports for
-Node.js and the browser can be written:
+`require()` and `import` can be written:
```js
-// ./node_modules/pkg/package.json
+// package.json
{
- "type": "module",
- "main": "./index.js",
+ "main": "./main-require.cjs",
"exports": {
- "./feature": {
- "import": "./feature-default.js",
- "browser": "./feature-browser.js"
- }
- }
+ "import": "./main-module.js",
+ "require": "./main-require.cjs"
+ },
+ "type": "module"
}
```
-When resolving the `"."` export, if no matching target is found, the `"main"`
-will be used as the final fallback.
+Node.js supports the following conditions:
-The conditions supported in Node.js condition matching:
-
-* `"default"` - the generic fallback that will always match. Can be a CommonJS
- or ES module file.
* `"import"` - matched when the package is loaded via `import` or
- `import()`. Can be any module format, this field does not set the type
- interpretation.
-* `"node"` - matched for any Node.js environment. Can be a CommonJS or ES
- module file.
+ `import()`. Can reference either an ES module or CommonJS file, as both
+ `import` and `import()` can load either ES module or CommonJS sources.
* `"require"` - matched when the package is loaded via `require()`.
+ As `require()` only supports CommonJS, the referenced file must be CommonJS.
+* `"node"` - matched for any Node.js environment. Can be a CommonJS or ES
+ module file. _This condition should always come after `"import"` or
+ `"require"`._
+* `"default"` - the generic fallback that will always match. Can be a CommonJS
+ or ES module file. _This condition should always come last._
Condition matching is applied in object order from first to last within the
-`"exports"` object.
-
-Using the `"require"` condition it is possible to define a package that will
-have a different exported value for CommonJS and ES modules, which can be a
-hazard in that it can result in having two separate instances of the same
-package in use in an application, which can cause a number of bugs.
+`"exports"` object. _The general rule is that conditions should be used
+from most specific to least specific in object order._
Other conditions such as `"browser"`, `"electron"`, `"deno"`, `"react-native"`,
-etc. could be defined in other runtimes or tools. Condition names must not start
-with `"."` or be numbers. Further restrictions, definitions or guidance on
-condition names may be provided in future.
+etc. are ignored by Node.js but may be used by other runtimes or tools.
+Further restrictions, definitions or guidance on condition names may be
+provided in the future.
+
+Using the `"import"` and `"require"` conditions can lead to some hazards,
+which are explained further in
+[the dual CommonJS/ES module packages section][].
+
+Conditional exports can also be extended to exports subpaths, for example:
+
+
+```js
+{
+ "main": "./main.js",
+ "exports": {
+ ".": "./main.js",
+ "./feature": {
+ "browser": "./feature-browser.js",
+ "default": "./feature.js"
+ }
+ }
+}
+```
+
+Defines a package where `require('pkg/feature')` and `import 'pkg/feature'`
+could provide different implementations between the browser and Node.js,
+given third-party tool support for a `"browser"` condition.
diff --git a/esm/customizing_esm_specifier_resolution_algorithm.md b/esm/customizing_esm_specifier_resolution_algorithm.md
index 81d43c35..9e0b4489 100644
--- a/esm/customizing_esm_specifier_resolution_algorithm.md
+++ b/esm/customizing_esm_specifier_resolution_algorithm.md
@@ -41,6 +41,8 @@ success!
+
+
diff --git a/esm/enabling.md b/esm/enabling.md
index f003e5f4..57ac49c7 100644
--- a/esm/enabling.md
+++ b/esm/enabling.md
@@ -10,9 +10,8 @@ ES module code:
* Files ending in `.mjs`.
-* Files ending in `.js`, or extensionless files, when the nearest parent
- `package.json` file contains a top-level field `"type"` with a value of
- `"module"`.
+* Files ending in `.js` when the nearest parent `package.json` file contains a
+ top-level field `"type"` with a value of `"module"`.
* Strings passed in as an argument to `--eval` or `--print`, or piped to
`node` via `STDIN`, with the flag `--input-type=module`.
@@ -27,9 +26,8 @@ or when referenced by `import` statements within ES module code:
* Files ending in `.cjs`.
-* Files ending in `.js`, or extensionless files, when the nearest parent
- `package.json` file contains a top-level field `"type"` with a value of
- `"commonjs"`.
+* Files ending in `.js` when the nearest parent `package.json` file contains a
+ top-level field `"type"` with a value of `"commonjs"`.
* Strings passed in as an argument to `--eval` or `--print`, or piped to
`node` via `STDIN`, with the flag `--input-type=commonjs`.
diff --git a/esm/exports_sugar.md b/esm/exports_sugar.md
index ffee250c..a85d0d11 100644
--- a/esm/exports_sugar.md
+++ b/esm/exports_sugar.md
@@ -23,46 +23,3 @@ can be written:
}
```
-When using [Conditional Exports][], the rule is that all keys in the object
-mapping must not start with a `"."` otherwise they would be indistinguishable
-from exports subpaths.
-
-
-```js
-{
- "exports": {
- ".": {
- "import": "./main.js",
- "require": "./main.cjs"
- }
- }
-}
-```
-
-can be written:
-
-
-```js
-{
- "exports": {
- "import": "./main.js",
- "require": "./main.cjs"
- }
-}
-```
-
-If writing any exports value that mixes up these two forms, an error will be
-thrown:
-
-
-```js
-{
- // Throws on resolution!
- "exports": {
- "./feature": "./lib/feature.js",
- "import": "./main.js",
- "require": "./main.cjs"
- }
-}
-```
-
diff --git a/esm/import_expressions.md b/esm/import_expressions.md
index d8507d13..2b564796 100644
--- a/esm/import_expressions.md
+++ b/esm/import_expressions.md
@@ -1,10 +1,4 @@
-Dynamic `import()` is supported in both CommonJS and ES modules. It can be used
-to include ES module files from CommonJS code.
-
-```js
-(async () => {
- await import('./my-app.mjs');
-})();
-```
+[Dynamic `import()`][] is supported in both CommonJS and ES modules. It can be
+used to include ES module files from CommonJS code.
diff --git a/esm/import_statements.md b/esm/import_statements.md
index 7b0a0bd2..5d5d5357 100644
--- a/esm/import_statements.md
+++ b/esm/import_statements.md
@@ -11,8 +11,8 @@ can either be an URL-style relative path like `'./file.mjs'` or a package name
like `'fs'`.
Like in CommonJS, files within packages can be accessed by appending a path to
-the package name; unless the package’s `package.json` contains an [`"exports"`
-field][], in which case files within packages need to be accessed via the path
+the package name; unless the package’s `package.json` contains an `"exports"`
+field, in which case files within packages need to be accessed via the path
defined in `"exports"`.
```js
@@ -28,3 +28,6 @@ import packageMain from 'commonjs-package'; // Works
import { method } from 'commonjs-package'; // Errors
```
+It is also possible to
+[import an ES or CommonJS module for its side effects only][].
+
diff --git a/esm/main_entry_point_export.md b/esm/main_entry_point_export.md
new file mode 100644
index 00000000..9fce1e7d
--- /dev/null
+++ b/esm/main_entry_point_export.md
@@ -0,0 +1,23 @@
+
+To set the main entry point for a package, it is advisable to define both
+`"exports"` and `"main"` in the package’s `package.json` file:
+
+
+```js
+{
+ "main": "./main.js",
+ "exports": "./main.js"
+}
+```
+
+The benefit of doing this is that when using the `"exports"` field all
+subpaths of the package will no longer be available to importers under
+`require('pkg/subpath.js')`, and instead they will get a new error,
+`ERR_PACKAGE_PATH_NOT_EXPORTED`.
+
+This encapsulation of exports provides more reliable guarantees
+about package interfaces for tools and when handling semver upgrades for a
+package. It is not a strong encapsulation since a direct require of any
+absolute subpath of the package such as
+`require('/path/to/node_modules/pkg/subpath.js')` will still load `subpath.js`.
+
diff --git a/esm/nested_conditions.md b/esm/nested_conditions.md
new file mode 100644
index 00000000..b24a3489
--- /dev/null
+++ b/esm/nested_conditions.md
@@ -0,0 +1,25 @@
+
+In addition to direct mappings, Node.js also supports nested condition objects.
+
+For example, to define a package that only has dual mode entry points for
+use in Node.js but not the browser:
+
+
+```js
+{
+ "main": "./main.js",
+ "exports": {
+ "browser": "./feature-browser.mjs",
+ "node": {
+ "import": "./feature-node.mjs",
+ "require": "./feature-node.cjs"
+ }
+ }
+}
+```
+
+Conditions continue to be matched in order as with flat conditions. If
+a nested conditional does not have any mapping it will continue checking
+the remaining conditions of the parent condition. In this way nested
+conditions behave analogously to nested JavaScript `if` statements.
+
diff --git a/esm/no_require_resolve.md b/esm/no_require_resolve.md
new file mode 100644
index 00000000..371e7ce2
--- /dev/null
+++ b/esm/no_require_resolve.md
@@ -0,0 +1,25 @@
+
+Former use cases relying on `require.resolve` to determine the resolved path
+of a module can be supported via `import.meta.resolve`, which is experimental
+and supported via the `--experimental-import-meta-resolve` flag:
+
+```js
+(async () => {
+ const dependencyAsset = await import.meta.resolve('component-lib/asset.css');
+})();
+```
+
+`import.meta.resolve` also accepts a second argument which is the parent module
+from which to resolve from:
+
+```js
+(async () => {
+ // Equivalent to import.meta.resolve('./dep')
+ await import.meta.resolve('./dep', import.meta.url);
+})();
+```
+
+This function is asynchronous since the ES module resolver in Node.js is
+asynchronous. With the introduction of [Top-Level Await][], these use cases
+will be easier as they won't require an async function wrapper.
+
diff --git a/esm/package_entry_points.md b/esm/package_entry_points.md
index f6e1e022..45db5142 100644
--- a/esm/package_entry_points.md
+++ b/esm/package_entry_points.md
@@ -1,12 +1,27 @@
-There are two fields that can define entry points for a package: `"main"` and
-`"exports"`. The `"main"` field is supported in all versions of Node.js, but its
-capabilities are limited: it only defines the main entry point of the package.
-The `"exports"` field, part of [Package Exports][], provides an alternative to
-`"main"` where the package main entry point can be defined while also
-encapsulating the package, preventing any other entry points besides those
-defined in `"exports"`. If package entry points are defined in both `"main"` and
-`"exports"`, the latter takes precedence in versions of Node.js that support
-`"exports"`. [Conditional Exports][] can also be used within `"exports"` to
-define different package entry points per environment.
+In a package’s `package.json` file, two fields can define entry points for a
+package: `"main"` and `"exports"`. The `"main"` field is supported in all
+versions of Node.js, but its capabilities are limited: it only defines the main
+entry point of the package.
+
+The `"exports"` field provides an alternative to `"main"` where the package
+main entry point can be defined while also encapsulating the package, preventing
+any other entry points besides those defined in `"exports"`. If package entry
+points are defined in both `"main"` and `"exports"`, the latter takes precedence
+in versions of Node.js that support `"exports"`. [Conditional Exports][] can
+also be used within `"exports"` to define different package entry points per
+environment, including whether the package is referenced via `require` or via
+`import`.
+
+If both `"exports"` and `"main"` are defined, the `"exports"` field takes
+precedence over `"main"`.
+
+Both `"main"` and `"exports"` entry points are not specific to ES modules or
+CommonJS; `"main"` will be overridden by `"exports"` in a `require` so it is
+not a CommonJS fallback.
+
+This is important with regard to `require`, since `require` of ES module files
+throws an error in all versions of Node.js. To create a package that works both
+in modern Node.js via `import` and `require` and also legacy Node.js versions,
+see [the dual CommonJS/ES module packages section][].
diff --git a/esm/package_exports.md b/esm/package_exports.md
deleted file mode 100644
index 3047c7ae..00000000
--- a/esm/package_exports.md
+++ /dev/null
@@ -1,86 +0,0 @@
-
-By default, all subpaths from a package can be imported (`import 'pkg/x.js'`).
-Custom subpath aliasing and encapsulation can be provided through the
-`"exports"` field.
-
-
-```js
-// ./node_modules/es-module-package/package.json
-{
- "exports": {
- "./submodule": "./src/submodule.js"
- }
-}
-```
-
-```js
-import submodule from 'es-module-package/submodule';
-// Loads ./node_modules/es-module-package/src/submodule.js
-```
-
-In addition to defining an alias, subpaths not defined by `"exports"` will
-throw when an attempt is made to import them:
-
-```js
-import submodule from 'es-module-package/private-module.js';
-// Throws ERR_MODULE_NOT_FOUND
-```
-
-> Note: this is not a strong encapsulation as any private modules can still be
-> loaded by absolute paths.
-
-Folders can also be mapped with package exports:
-
-
-```js
-// ./node_modules/es-module-package/package.json
-{
- "exports": {
- "./features/": "./src/features/"
- }
-}
-```
-
-```js
-import feature from 'es-module-package/features/x.js';
-// Loads ./node_modules/es-module-package/src/features/x.js
-```
-
-If a package has no exports, setting `"exports": false` can be used instead of
-`"exports": {}` to indicate the package does not intend for submodules to be
-exposed.
-
-Any invalid exports entries will be ignored. This includes exports not
-starting with `"./"` or a missing trailing `"/"` for directory exports.
-
-Array fallback support is provided for exports, similarly to import maps
-in order to be forwards-compatible with possible fallback workflows in future:
-
-
-```js
-{
- "exports": {
- "./submodule": ["not:valid", "./submodule.js"]
- }
-}
-```
-
-Since `"not:valid"` is not a supported target, `"./submodule.js"` is used
-instead as the fallback, as if it were the only target.
-
-Defining a `"."` export will define the main entry point for the package,
-and will always take precedence over the `"main"` field in the `package.json`.
-
-This allows defining a different entry point for Node.js versions that support
-ECMAScript modules and versions that don't, for example:
-
-
-```js
-{
- "main": "./main-legacy.cjs",
- "exports": {
- ".": "./main-modern.cjs"
- }
-}
-```
-
diff --git a/esm/package_exports_fallbacks.md b/esm/package_exports_fallbacks.md
new file mode 100644
index 00000000..6f7b6f46
--- /dev/null
+++ b/esm/package_exports_fallbacks.md
@@ -0,0 +1,16 @@
+
+For possible new specifier support in future, array fallbacks are
+supported for all invalid specifiers:
+
+
+```js
+{
+ "exports": {
+ "./submodule": ["not:valid", "./submodule.js"]
+ }
+}
+```
+
+Since `"not:valid"` is not a valid specifier, `"./submodule.js"` is used
+instead as the fallback, as if it were the only target.
+
diff --git a/esm/package_json_type_field.md b/esm/package_json_type_field.md
index 9c7fc496..a3a7da9b 100644
--- a/esm/package_json_type_field.md
+++ b/esm/package_json_type_field.md
@@ -1,7 +1,7 @@
-Files ending with `.js` or lacking any extension will be loaded as ES modules
-when the nearest parent `package.json` file contains a top-level field `"type"`
-with a value of `"module"`.
+Files ending with `.js` will be loaded as ES modules when the nearest parent
+`package.json` file contains a top-level field `"type"` with a value of
+`"module"`.
The nearest parent `package.json` is defined as the first `package.json` found
when searching in the current folder, that folder’s parent, and so on up
@@ -21,14 +21,12 @@ node --experimental-modules my-app.js # Runs as ES module
```
If the nearest parent `package.json` lacks a `"type"` field, or contains
-`"type": "commonjs"`, extensionless and `.js` files are treated as CommonJS.
-If the volume root is reached and no `package.json` is found,
-Node.js defers to the default, a `package.json` with no `"type"`
-field. "Extensionless" refers to file paths which do not contain
-an extension as opposed to optionally dropping a file extension in a specifier.
-
-`import` statements of `.js` and extensionless files are treated as ES modules
-if the nearest parent `package.json` contains `"type": "module"`.
+`"type": "commonjs"`, `.js` files are treated as CommonJS. If the volume root is
+reached and no `package.json` is found, Node.js defers to the default, a
+`package.json` with no `"type"` field.
+
+`import` statements of `.js` files are treated as ES modules if the nearest
+parent `package.json` contains `"type": "module"`.
```js
// my-app.js, part of the same example as above
diff --git a/esm/package_scope_and_file_extensions.md b/esm/package_scope_and_file_extensions.md
index f2a91c3f..6f8ba741 100644
--- a/esm/package_scope_and_file_extensions.md
+++ b/esm/package_scope_and_file_extensions.md
@@ -1,12 +1,11 @@
-A folder containing a `package.json` file, and all subfolders below that
-folder down until the next folder containing another `package.json`, is
-considered a _package scope_. The `"type"` field defines how `.js` and
-extensionless files should be treated within a particular `package.json` file’s
-package scope. Every package in a project’s `node_modules` folder contains its
-own `package.json` file, so each project’s dependencies have their own package
-scopes. A `package.json` lacking a `"type"` field is treated as if it contained
-`"type": "commonjs"`.
+A folder containing a `package.json` file, and all subfolders below that folder
+down until the next folder containing another `package.json`, is considered a
+_package scope_. The `"type"` field defines how `.js` files should be treated
+within a particular `package.json` file’s package scope. Every package in a
+project’s `node_modules` folder contains its own `package.json` file, so each
+project’s dependencies have their own package scopes. A `package.json` lacking a
+`"type"` field is treated as if it contained `"type": "commonjs"`.
The package scope applies not only to initial entry points (`node
--experimental-modules my-app.js`) but also to files referenced by `import`
diff --git a/esm/resolver_algorithm.md b/esm/resolver_algorithm.md
index 24708a8a..0aa19a2e 100644
--- a/esm/resolver_algorithm.md
+++ b/esm/resolver_algorithm.md
@@ -1,13 +1,14 @@
The algorithm to load an ES module specifier is given through the
**ESM_RESOLVE** method below. It returns the resolved URL for a
-module specifier relative to a parentURL, in addition to the unique module
-format for that resolved URL given by the **ESM_FORMAT** routine.
+module specifier relative to a parentURL.
-The _"module"_ format is returned for an ECMAScript Module, while the
-_"commonjs"_ format is used to indicate loading through the legacy
-CommonJS loader. Additional formats such as _"addon"_ can be extended in future
-updates.
+The algorithm to determine the module format of a resolved URL is
+provided by **ESM_FORMAT**, which returns the unique module
+format for any file. The _"module"_ format is returned for an ECMAScript
+Module, while the _"commonjs"_ format is used to indicate loading through the
+legacy CommonJS loader. Additional formats such as _"addon"_ can be extended in
+future updates.
In the following algorithms, all subroutine errors are propagated as errors
of these top-level routines unless stated otherwise.
@@ -15,6 +16,17 @@ of these top-level routines unless stated otherwise.
_defaultEnv_ is the conditional environment name priority array,
`["node", "import"]`.
+The resolver can throw the following errors:
+* _Invalid Module Specifier_: Module specifier is an invalid URL, package name
+ or package subpath specifier.
+* _Invalid Package Configuration_: package.json configuration is invalid or
+ contains an invalid configuration.
+* _Invalid Package Target_: Package exports define a target module within the
+ package that is an invalid type or string target.
+* _Package Path Not Exported_: Package exports do not define or permit a target
+ subpath in the package for the given module.
+* _Module Not Found_: The package or module requested does not exist.
+
Resolver algorithm specification
@@ -25,7 +37,7 @@ _defaultEnv_ is the conditional environment name priority array,
> 1. Set _resolvedURL_ to the result of parsing and reserializing
> _specifier_ as a URL.
> 1. Otherwise, if _specifier_ starts with _"/"_, then
-> 1. Throw an _Invalid Specifier_ error.
+> 1. Throw an _Invalid Module Specifier_ error.
> 1. Otherwise, if _specifier_ starts with _"./"_ or _"../"_, then
> 1. Set _resolvedURL_ to the URL resolution of _specifier_ relative to
> _parentURL_.
@@ -35,26 +47,28 @@ _defaultEnv_ is the conditional environment name priority array,
> **PACKAGE_RESOLVE**(_specifier_, _parentURL_).
> 1. If _resolvedURL_ contains any percent encodings of _"/"_ or _"\\"_ (_"%2f"_
> and _"%5C"_ respectively), then
-> 1. Throw an _Invalid Specifier_ error.
-> 1. If the file at _resolvedURL_ does not exist, then
+> 1. Throw an _Invalid Module Specifier_ error.
+> 1. If _resolvedURL_ does not end with a trailing _"/"_ and the file at
+> _resolvedURL_ does not exist, then
> 1. Throw a _Module Not Found_ error.
> 1. Set _resolvedURL_ to the real path of _resolvedURL_.
> 1. Let _format_ be the result of **ESM_FORMAT**(_resolvedURL_).
> 1. Load _resolvedURL_ as module format, _format_.
+> 1. Return _resolvedURL_.
**PACKAGE_RESOLVE**(_packageSpecifier_, _parentURL_)
> 1. Let _packageName_ be *undefined*.
> 1. Let _packageSubpath_ be *undefined*.
> 1. If _packageSpecifier_ is an empty string, then
-> 1. Throw an _Invalid Specifier_ error.
+> 1. Throw an _Invalid Module Specifier_ error.
> 1. Otherwise,
> 1. If _packageSpecifier_ does not contain a _"/"_ separator, then
-> 1. Throw an _Invalid Specifier_ error.
+> 1. Throw an _Invalid Module Specifier_ error.
> 1. Set _packageName_ to the substring of _packageSpecifier_
> until the second _"/"_ separator or the end of the string.
> 1. If _packageName_ starts with _"."_ or contains _"\\"_ or _"%"_, then
-> 1. Throw an _Invalid Specifier_ error.
+> 1. Throw an _Invalid Module Specifier_ error.
> 1. Let _packageSubpath_ be _undefined_.
> 1. If the length of _packageSpecifier_ is greater than the length of
> _packageName_, then
@@ -62,13 +76,13 @@ _defaultEnv_ is the conditional environment name priority array,
> _packageSpecifier_ from the position at the length of _packageName_.
> 1. If _packageSubpath_ contains any _"."_ or _".."_ segments or percent
> encoded strings for _"/"_ or _"\\"_, then
-> 1. Throw an _Invalid Specifier_ error.
+> 1. Throw an _Invalid Module Specifier_ error.
> 1. Set _selfUrl_ to the result of
> **SELF_REFERENCE_RESOLVE**(_packageName_, _packageSubpath_, _parentURL_).
> 1. If _selfUrl_ isn't empty, return _selfUrl_.
> 1. If _packageSubpath_ is _undefined_ and _packageName_ is a Node.js builtin
> module, then
-> 1. Return the string _"node:"_ concatenated with _packageSpecifier_.
+> 1. Return the string _"nodejs:"_ concatenated with _packageSpecifier_.
> 1. While _parentURL_ is not the file system root,
> 1. Let _packageURL_ be the URL resolution of _"node_modules/"_
> concatenated with _packageSpecifier_, relative to _parentURL_.
@@ -77,6 +91,8 @@ _defaultEnv_ is the conditional environment name priority array,
> 1. Set _parentURL_ to the parent URL path of _parentURL_.
> 1. Continue the next loop iteration.
> 1. Let _pjson_ be the result of **READ_PACKAGE_JSON**(_packageURL_).
+> 1. If _packageSubpath_ is equal to _"./"_, then
+> 1. Return _packageURL_ + _"/"_.
> 1. If _packageSubpath_ is _undefined__, then
> 1. Return the result of **PACKAGE_MAIN_RESOLVE**(_packageURL_,
> _pjson_).
@@ -98,6 +114,8 @@ _defaultEnv_ is the conditional environment name priority array,
> 1. If _pjson_ does not include an _"exports"_ property, then
> 1. Return **undefined**.
> 1. If _pjson.name_ is equal to _packageName_, then
+> 1. If _packageSubpath_ is equal to _"./"_, then
+> 1. Return _packageURL_ + _"/"_.
> 1. If _packageSubpath_ is _undefined_, then
> 1. Return the result of **PACKAGE_MAIN_RESOLVE**(_packageURL_, _pjson_).
> 1. Otherwise,
@@ -115,7 +133,7 @@ _defaultEnv_ is the conditional environment name priority array,
> 1. Throw a _Module Not Found_ error.
> 1. If _pjson.exports_ is not **null** or **undefined**, then
> 1. If _exports_ is an Object with both a key starting with _"."_ and a key
-> not starting with _"."_, throw an "Invalid Package Configuration" error.
+> not starting with _"."_, throw an _Invalid Package Configuration_ error.
> 1. If _pjson.exports_ is a String or Array, or an Object containing no
> keys starting with _"."_, then
> 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_,
@@ -124,6 +142,7 @@ _defaultEnv_ is the conditional environment name priority array,
> 1. Let _mainExport_ be the _"."_ property in _pjson.exports_.
> 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_,
> _mainExport_, _""_).
+> 1. Throw a _Package Path Not Exported_ error.
> 1. If _pjson.main_ is a String, then
> 1. Let _resolvedMain_ be the URL resolution of _packageURL_, "/", and
> _pjson.main_.
@@ -138,7 +157,7 @@ _defaultEnv_ is the conditional environment name priority array,
**PACKAGE_EXPORTS_RESOLVE**(_packageURL_, _packagePath_, _exports_)
> 1. If _exports_ is an Object with both a key starting with _"."_ and a key not
-> starting with _"."_, throw an "Invalid Package Configuration" error.
+> starting with _"."_, throw an _Invalid Package Configuration_ error.
> 1. If _exports_ is an Object and all keys of _exports_ start with _"."_, then
> 1. Set _packagePath_ to _"./"_ concatenated with _packagePath_.
> 1. If _packagePath_ is a key of _exports_, then
@@ -154,59 +173,58 @@ _defaultEnv_ is the conditional environment name priority array,
> of the length of _directory_.
> 1. Return **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _target_,
> _subpath_, _defaultEnv_).
-> 1. Throw a _Module Not Found_ error.
+> 1. Throw a _Package Path Not Exported_ error.
**PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _target_, _subpath_, _env_)
> 1. If _target_ is a String, then
-> 1. If _target_ does not start with _"./"_, throw a _Module Not Found_
-> error.
-> 1. If _subpath_ has non-zero length and _target_ does not end with _"/"_,
-> throw a _Module Not Found_ error.
-> 1. If _target_ or _subpath_ contain any _"node_modules"_ segments including
-> _"node_modules"_ percent-encoding, throw a _Module Not Found_ error.
+> 1. If _target_ does not start with _"./"_ or contains any _"node_modules"_
+> segments including _"node_modules"_ percent-encoding, throw an
+> _Invalid Package Target_ error.
> 1. Let _resolvedTarget_ be the URL resolution of the concatenation of
> _packageURL_ and _target_.
-> 1. If _resolvedTarget_ is contained in _packageURL_, then
-> 1. Let _resolved_ be the URL resolution of the concatenation of
-> _subpath_ and _resolvedTarget_.
-> 1. If _resolved_ is contained in _resolvedTarget_, then
-> 1. Return _resolved_.
+> 1. If _resolvedTarget_ is not contained in _packageURL_, throw an
+> _Invalid Package Target_ error.
+> 1. If _subpath_ has non-zero length and _target_ does not end with _"/"_,
+> throw an _Invalid Module Specifier_ error.
+> 1. Let _resolved_ be the URL resolution of the concatenation of
+> _subpath_ and _resolvedTarget_.
+> 1. If _resolved_ is not contained in _resolvedTarget_, throw an
+> _Invalid Module Specifier_ error.
+> 1. Return _resolved_.
> 1. Otherwise, if _target_ is a non-null Object, then
> 1. If _exports_ contains any index property keys, as defined in ECMA-262
> [6.1.7 Array Index][], throw an _Invalid Package Configuration_ error.
> 1. For each property _p_ of _target_, in object insertion order as,
> 1. If _env_ contains an entry for _p_, then
> 1. Let _targetValue_ be the value of the _p_ property in _target_.
-> 1. Let _resolved_ be the result of **PACKAGE_EXPORTS_TARGET_RESOLVE**
-> (_packageURL_, _targetValue_, _subpath_, _env_).
-> 1. Assert: _resolved_ is a String.
-> 1. Return _resolved_.
+> 1. Return the result of **PACKAGE_EXPORTS_TARGET_RESOLVE**(
+> _packageURL_, _targetValue_, _subpath_, _env_), continuing the
+> loop on any _Package Path Not Exported_ error.
+> 1. Throw a _Package Path Not Exported_ error.
> 1. Otherwise, if _target_ is an Array, then
+> 1. If _target.length is zero, throw an _Invalid Package Target_ error.
> 1. For each item _targetValue_ in _target_, do
> 1. If _targetValue_ is an Array, continue the loop.
-> 1. Let _resolved_ be the result of
-> **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_, _targetValue_,
-> _subpath_, _env_), continuing the loop on abrupt completion.
-> 1. Assert: _resolved_ is a String.
-> 1. Return _resolved_.
-> 1. Throw a _Module Not Found_ error.
+> 1. Return the result of **PACKAGE_EXPORTS_TARGET_RESOLVE**(_packageURL_,
+> _targetValue_, _subpath_, _env_), continuing the loop on any
+> _Package Path Not Exported_ or _Invalid Package Target_ error.
+> 1. Throw the last fallback resolution error.
+> 1. Otherwise throw an _Invalid Package Target_ error.
**ESM_FORMAT**(_url_)
-> 1. Assert: _url_ corresponds to an existing file pathname.
+> 1. Assert: _url_ corresponds to an existing file.
> 1. Let _pjson_ be the result of **READ_PACKAGE_SCOPE**(_url_).
> 1. If _url_ ends in _".mjs"_, then
> 1. Return _"module"_.
> 1. If _url_ ends in _".cjs"_, then
> 1. Return _"commonjs"_.
> 1. If _pjson?.type_ exists and is _"module"_, then
-> 1. If _url_ ends in _".js"_ or lacks a file extension, then
+> 1. If _url_ ends in _".js"_, then
> 1. Return _"module"_.
> 1. Throw an _Unsupported File Extension_ error.
> 1. Otherwise,
-> 1. If _url_ lacks a file extension, then
-> 1. Return _"commonjs"_.
> 1. Throw an _Unsupported File Extension_ error.
**READ_PACKAGE_SCOPE**(_url_)
diff --git a/esm/self_referencing_a_package_using_its_name.md b/esm/self_referencing_a_package_using_its_name.md
new file mode 100644
index 00000000..ca1f3faa
--- /dev/null
+++ b/esm/self_referencing_a_package_using_its_name.md
@@ -0,0 +1,44 @@
+
+Within a package, the values defined in the package’s
+`package.json` `"exports"` field can be referenced via the package’s name.
+For example, assuming the `package.json` is:
+
+```json
+// package.json
+{
+ "name": "a-package",
+ "exports": {
+ ".": "./main.mjs",
+ "./foo": "./foo.js"
+ }
+}
+```
+
+Then any module _in that package_ can reference an export in the package itself:
+
+```js
+// ./a-module.mjs
+import { something } from 'a-package'; // Imports "something" from ./main.mjs.
+```
+
+Self-referencing is available only if `package.json` has `exports`, and will
+allow importing only what that `exports` (in the `package.json`) allows.
+So the code below, given the package above, will generate a runtime error:
+
+```js
+// ./another-module.mjs
+
+// Imports "another" from ./m.mjs. Fails because
+// the "package.json" "exports" field
+// does not provide an export named "./m.mjs".
+import { another } from 'a-package/m.mjs';
+```
+
+Self-referencing is also available when using `require`, both in an ES module,
+and in a CommonJS one. For example, this code will also work:
+
+```js
+// ./a-module.js
+const { something } = require('a-package/foo'); // Loads from ./foo.js.
+```
+
diff --git a/esm/subpath_exports.md b/esm/subpath_exports.md
new file mode 100644
index 00000000..28b96d4b
--- /dev/null
+++ b/esm/subpath_exports.md
@@ -0,0 +1,56 @@
+
+When using the `"exports"` field, custom subpaths can be defined along
+with the main entry point by treating the main entry point as the
+`"."` subpath:
+
+
+```js
+{
+ "main": "./main.js",
+ "exports": {
+ ".": "./main.js",
+ "./submodule": "./src/submodule.js"
+ }
+}
+```
+
+Now only the defined subpath in `"exports"` can be imported by a
+consumer:
+
+```js
+import submodule from 'es-module-package/submodule';
+// Loads ./node_modules/es-module-package/src/submodule.js
+```
+
+While other subpaths will error:
+
+```js
+import submodule from 'es-module-package/private-module.js';
+// Throws ERR_PACKAGE_PATH_NOT_EXPORTED
+```
+
+Entire folders can also be mapped with package exports:
+
+
+```js
+// ./node_modules/es-module-package/package.json
+{
+ "exports": {
+ "./features/": "./src/features/"
+ }
+}
+```
+
+With the above, all modules within the `./src/features/` folder
+are exposed deeply to `import` and `require`:
+
+```js
+import feature from 'es-module-package/features/x.js';
+// Loads ./node_modules/es-module-package/src/features/x.js
+```
+
+When using folder mappings, ensure that you do want to expose every
+module inside the subfolder. Any modules which are not public
+should be moved to another folder to retain the encapsulation
+benefits of exports.
+
diff --git a/esm/transpiler_loader.md b/esm/transpiler_loader.md
index 5f865e30..fcd80053 100644
--- a/esm/transpiler_loader.md
+++ b/esm/transpiler_loader.md
@@ -4,7 +4,7 @@ JavaScript using the [`transformSource` hook][]. Before that hook gets called,
however, other hooks need to tell Node.js not to throw an error on unknown file
types; and to tell Node.js how to load this new file type.
-This is obviously less performant than transpiling source files before running
+This is less performant than transpiling source files before running
Node.js; a transpiler loader should only be used for development and testing
purposes.
diff --git a/esm/writing_dual_packages_while_avoiding_or_minimizing_hazards.md b/esm/writing_dual_packages_while_avoiding_or_minimizing_hazards.md
index 38217056..a3ddf5a8 100644
--- a/esm/writing_dual_packages_while_avoiding_or_minimizing_hazards.md
+++ b/esm/writing_dual_packages_while_avoiding_or_minimizing_hazards.md
@@ -9,7 +9,7 @@ would be usable by any version of Node.js, since `import` can refer to CommonJS
files; but it would not provide any of the advantages of using ES module syntax.
A package could also switch from CommonJS to ES module syntax in a breaking
-change version bump. This has the obvious disadvantage that the newest version
+change version bump. This has the disadvantage that the newest version
of the package would only be usable in ES module-supporting versions of Node.js.
Every pattern has tradeoffs, but there are two broad approaches that satisfy the
diff --git a/fs/filehandle_appendfile_data_options.md b/fs/filehandle_appendfile_data_options.md
index 4f31f8ef..32fa218b 100644
--- a/fs/filehandle_appendfile_data_options.md
+++ b/fs/filehandle_appendfile_data_options.md
@@ -4,15 +4,11 @@ added: v10.0.0
* `data` {string|Buffer}
* `options` {Object|string}
* `encoding` {string|null} **默认值:** `'utf8'`。
- * `mode` {integer} **默认值:** `0o666`
- * `flag` {string} 参阅[支持的文件系统标志][support of file system `flags`]。**默认值:** `'a'`。
* 返回: {Promise}
-异步地将数据追加到文件,如果文件尚不存在则创建该文件。
-`data` 可以是字符串或 [`Buffer`]。
-`Promise` 将会在成功时解决,且不带参数。
+[`filehandle.writeFile()`] 的别名。
-如果 `options` 是字符串,则它指定字符编码。
+当在文件句柄上进行操作时,无法将模式更改为使用 [`fsPromises.open()`] 设置的模式。
+因此,这等效于 [`filehandle.writeFile()`]。
-`FileHandle` 必须被打开用以追加。
diff --git a/fs/filehandle_readfile_options.md b/fs/filehandle_readfile_options.md
index d25d0ea7..0a447670 100644
--- a/fs/filehandle_readfile_options.md
+++ b/fs/filehandle_readfile_options.md
@@ -2,8 +2,7 @@
added: v10.0.0
-->
* `options` {Object|string}
- * `encoding` {string|null} **默认值:** `null`
- * `flag` {string} 参阅[支持的文件系统标志][support of file system `flags`]。**默认值:** `'r'`。
+ * `encoding` {string|null} **默认值:** `null`。
* 返回: {Promise}
异步地读取文件的全部内容。
@@ -14,10 +13,6 @@ added: v10.0.0
如果 `options` 是字符串,则它指定字符编码。
-当 `path` 是目录时,`fsPromises.readFile()` 的行为是特定于平台的。
-在 macOS、Linux 和 Windows 上,promise 将会被拒绝并带上一个错误。
-在 FreeBSD 上,则将会返回目录内容的表示。
-
`FileHandle` 必须支持读取。
如果对文件句柄进行了一次或多次 `filehandle.read()` 调用,然后再调用 `filehandle.readFile()`,则将从当前位置读取数据,直到文件结束。
diff --git a/fs/filehandle_writefile_data_options.md b/fs/filehandle_writefile_data_options.md
index 235206cf..6c1e09ae 100644
--- a/fs/filehandle_writefile_data_options.md
+++ b/fs/filehandle_writefile_data_options.md
@@ -4,8 +4,6 @@ added: v10.0.0
* `data` {string|Buffer|Uint8Array}
* `options` {Object|string}
* `encoding` {string|null} **默认值:** `'utf8'`。
- * `mode` {integer} **默认值:** `0o666`。
- * `flag` {string} 参阅[支持的文件系统标志][support of file system `flags`]。**默认值:** `'w'`。
* 返回: {Promise}
diff --git a/fs/fs_existssync_path.md b/fs/fs_existssync_path.md
index a3ad2b36..ecb6e9f4 100644
--- a/fs/fs_existssync_path.md
+++ b/fs/fs_existssync_path.md
@@ -20,7 +20,7 @@ changes:
```js
if (fs.existsSync('/etc/passwd')) {
- console.log('文件已存在');
+ console.log('路径已存在');
}
```
diff --git a/fs/fs_watchfile_filename_options_listener.md b/fs/fs_watchfile_filename_options_listener.md
index 4043e4fa..38c47e1e 100644
--- a/fs/fs_watchfile_filename_options_listener.md
+++ b/fs/fs_watchfile_filename_options_listener.md
@@ -1,6 +1,9 @@
-* `authority` {string|URL}
+* `authority` {string|URL} The remote HTTP/2 server to connect to. This must
+ be in the form of a minimal, valid URL with the `http://` or `https://`
+ prefix, host name, and IP port (if a non-default port is used). Userinfo
+ (user ID and password), path, querystring, and fragment details in the
+ URL will be ignored.
* `options` {Object}
* `maxDeflateDynamicTableSize` {number} Sets the maximum dynamic table size
for deflating header fields. **Default:** `4Kib`.
@@ -63,6 +67,9 @@ changes:
* `selectPadding` {Function} When `options.paddingStrategy` is equal to
`http2.constants.PADDING_STRATEGY_CALLBACK`, provides the callback function
used to determine the padding. See [Using `options.selectPadding()`][].
+ * `protocol` {string} The protocol to connect with, if not set in the
+ `authority`. Value may be either `'http:'` or `'https:'`. **Default:**
+ `'https:'`
* `settings` {HTTP/2 Settings Object} The initial settings to send to the
remote peer upon connection.
* `createConnection` {Function} An optional callback that receives the `URL`
diff --git a/http2/request_headers.md b/http2/request_headers.md
index 27594c97..b5a18f85 100644
--- a/http2/request_headers.md
+++ b/http2/request_headers.md
@@ -19,7 +19,7 @@ console.log(request.headers);
See [HTTP/2 Headers Object][].
-In HTTP/2, the request path, hostname, protocol, and method are represented as
+In HTTP/2, the request path, host name, protocol, and method are represented as
special headers prefixed with the `:` character (e.g. `':path'`). These special
headers will be included in the `request.headers` object. Care must be taken not
to inadvertently modify these special headers or errors may occur. For instance,
diff --git a/modules/all_together.md b/modules/all_together.md
index 9a991961..3bfc3ed3 100644
--- a/modules/all_together.md
+++ b/modules/all_together.md
@@ -18,7 +18,7 @@ require(X) from module at path Y
c. THROW "not found"
4. LOAD_SELF_REFERENCE(X, dirname(Y))
5. LOAD_NODE_MODULES(X, dirname(Y))
-7. THROW "not found"
+6. THROW "not found"
LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text. STOP
diff --git a/modules/require_id.md b/modules/require_id.md
index 0cc0f64c..fbe16405 100644
--- a/modules/require_id.md
+++ b/modules/require_id.md
@@ -10,9 +10,11 @@ added: v0.1.13
用于引入模块、`JSON`、或本地文件。
可以从 `node_modules` 引入模块。
可以使用相对路径(例如 `./`、`./foo`、`./bar/baz`、`../foo`)引入本地模块或 JSON 文件,路径会根据 [`__dirname`] 定义的目录名或当前工作目录进行处理。
+POSIX 风格的相对路径会以与操作系统无关的方式解析,这意味着上面的示例将会在 Windows 上以与在 Unix 系统上相同的方式工作。
```js
-// 引入本地模块:
+// 使用相对于 `__dirname` 或当前工作目录的路径引入一个本地模块。
+// (在 Windows 上,这会解析为 .\path\myLocalModule。)
const myLocalModule = require('./path/myLocalModule');
// 引入 JSON 文件:
diff --git a/modules/the_module_object_1.md b/modules/the_module_object_1.md
index 3039cd6f..18841ccd 100644
--- a/modules/the_module_object_1.md
+++ b/modules/the_module_object_1.md
@@ -5,8 +5,7 @@ added: v0.3.7
* {Object}
-为 `Module` 实例提供通用方法。
-`module` 变量常见于文件模块中。
+为 `Module` 实例提供通用方法,`module` 变量常见于文件模块中。
通过 `require('module')` 获取。
diff --git a/n-api/napi_env.md b/n-api/napi_env.md
index 185f75fc..d1012788 100644
--- a/n-api/napi_env.md
+++ b/n-api/napi_env.md
@@ -4,6 +4,10 @@ implementation can use to persist VM-specific state. This structure is passed
to native functions when they're invoked, and it must be passed back when
making N-API calls. Specifically, the same `napi_env` that was passed in when
the initial native function was called must be passed to any subsequent
-nested N-API calls. Caching the `napi_env` for the purpose of general reuse is
-not allowed.
+nested N-API calls. Caching the `napi_env` for the purpose of general reuse,
+and passing the `napi_env` between instances of the same addon running on
+different [`Worker`][] threads is not allowed. The `napi_env` becomes invalid
+when an instance of a native addon is unloaded. Notification of this event is
+delivered through the callbacks given to [`napi_add_env_cleanup_hook`][] and
+[`napi_set_instance_data`][].
diff --git a/n-api/napi_is_promise.md b/n-api/napi_is_promise.md
index 0b3a23e6..72acc816 100644
--- a/n-api/napi_is_promise.md
+++ b/n-api/napi_is_promise.md
@@ -5,12 +5,12 @@ napiVersion: 1
```C
napi_status napi_is_promise(napi_env env,
- napi_value promise,
+ napi_value value,
bool* is_promise);
```
* `[in] env`: The environment that the API is invoked under.
-* `[in] promise`: The promise to examine
+* `[in] value`: The value to examine
* `[out] is_promise`: Flag indicating whether `promise` is a native promise
object (that is, a promise object created by the underlying engine).
diff --git a/n-api/napi_reference_unref.md b/n-api/napi_reference_unref.md
index 4d75e5bc..9f49749a 100644
--- a/n-api/napi_reference_unref.md
+++ b/n-api/napi_reference_unref.md
@@ -6,7 +6,7 @@ napiVersion: 1
```C
NAPI_EXTERN napi_status napi_reference_unref(napi_env env,
napi_ref ref,
- uint32_t* result););
+ uint32_t* result);
```
* `[in] env`: The environment that the API is invoked under.
diff --git a/n-api/napi_unref_threadsafe_function.md b/n-api/napi_unref_threadsafe_function.md
index 03ba586a..22dd5190 100644
--- a/n-api/napi_unref_threadsafe_function.md
+++ b/n-api/napi_unref_threadsafe_function.md
@@ -120,6 +120,9 @@ This API may only be called from the main thread.
+
+
+
diff --git a/net/identifying_paths_for_ipc_connections.md b/net/identifying_paths_for_ipc_connections.md
index fd898ceb..a3c582eb 100644
--- a/net/identifying_paths_for_ipc_connections.md
+++ b/net/identifying_paths_for_ipc_connections.md
@@ -4,13 +4,13 @@
在 Unix 上,本地域也称为 Unix 域。
参数 `path` 是文件系统路径名。
-它被截断为 `sizeof(sockaddr_un.sun_path) - 1` 的长度,该长度因操作系统而异,在 91 至 107 字节之间。
+它会被截断为依赖于系统的 `sizeof(sockaddr_un.sun_path) - 1` 的长度。
典型值在 Linux 上为 107,在 macOS 上为 103。
-该路径受到与创建文件相同的命名约定和权限检查。
-如果创建 Unix 域套接字(作为文件系统路径可见)并与 Node.js 的 API 抽象之一(例如 [`net.createServer()`])一起使用,则它将作为 [`server.close()`] 的一部分取消链接。
-另一方面,如果在这些抽象之外创建和使用它,则用户需要手动删除它。
-当路径由 Node.js API 创建但程序突然崩溃时,同样适用。
-简而言之,一旦成功创建的 Unix 域套接字将在文件系统中可见,并将持续到取消链接。
+如果一个 Node.js API 的抽象创建了 Unix 域 socket,则它也可以 unlink 该 Unix 域 socket。
+例如,[`net.createServer()`] 可以创建 Unix 域 socket,而 [`server.close()`] 可以 unlink 它。
+但是,如果用户在这些抽象之外创建 Unix 域 socket,则用户需要自己删除它。
+当 Node.js API 创建 Unix 域 socket 但该程序随后崩溃时,情况也是如此。
+简而言之,Unix 域 socket 会在文件系统中可见,且持续到被 unlink。
在 Windows 上,本地域通过命名管道实现。路径必须是以 `\\?\pipe\` 或 `\\.\pipe\` 为入口。路径允许任何字符,但后面的字符可能会对管道名称进行一些处理,例如解析 `..` 序列。尽管如此,管道空间是平面的。管道不会持续,当最后一次引用关闭时,管道就会被删除。
diff --git a/net/socket_setnodelay_nodelay.md b/net/socket_setnodelay_nodelay.md
index 5bcf8447..af480b20 100644
--- a/net/socket_setnodelay_nodelay.md
+++ b/net/socket_setnodelay_nodelay.md
@@ -5,4 +5,12 @@ added: v0.1.90
* `noDelay` {boolean} **默认值:** `true`。
* 返回: {net.Socket} Socket 本身。
-禁止 Nagle 算法。默认情况下 TCP 连接使用 Nagle 算法,在发送之前缓冲数据。将 `noDelay` 设置为 `true` 将会在每次 `socket.write()` 被调用的时候立即发送数据。
+启用或禁用 Nagle 算法的使用。
+
+当TCP 连接被创建时,它会启用 Nagle 算法。
+
+Nagle 算法会延迟数据,然后再通过网络发送数据。
+它会尝试以延迟为代价优化吞吐量。
+
+为 `noDelay` 传入 `true` 或不传参数,则会禁用 Nagle 的 socket 算法。
+为 `noDelay` 传入 `false` 则会启用 Nagle 算法。
diff --git a/net/socket_write_data_encoding_callback.md b/net/socket_write_data_encoding_callback.md
index 7f13caca..471c1813 100644
--- a/net/socket_write_data_encoding_callback.md
+++ b/net/socket_write_data_encoding_callback.md
@@ -7,7 +7,8 @@ added: v0.1.90
* `callback` {Function}
* 返回: {boolean}
-在 socket 上发送数据。第二个参数制定了字符串的编码 - 默认是 UTF8 编码。
+在 socket 上发送数据。第二个参数制定了字符串的编码。
+默认是 UTF8 编码。
如果全部数据都成功刷新到内核的缓冲则返回 `true`。如果全部或部分数据在用户内中排队,则返回 `false`。当缓冲再次空闲的时候将触发 [`'drain'`][] 事件。
diff --git a/path/path.md b/path/path.md
index badf7670..1724fbf6 100644
--- a/path/path.md
+++ b/path/path.md
@@ -3,7 +3,7 @@
> 稳定性: 2 - 稳定
-`path` 模块提供用于处理文件路径和目录路径的实用工具。
+`path` 模块提供了一些用于处理文件与目录的路径的实用工具。
它可以使用以下方式访问:
```js
diff --git a/path/path_basename_path_ext.md b/path/path_basename_path_ext.md
index 4787b0c8..e6d9db2d 100644
--- a/path/path_basename_path_ext.md
+++ b/path/path_basename_path_ext.md
@@ -3,7 +3,7 @@ added: v0.1.25
changes:
- version: v6.0.0
pr-url: https://github.com/nodejs/node/pull/5348
- description: Passing a non-string as the `path` argument will throw now.
+ description: 现在将非字符串作为 `path` 参数传入会抛出异常。
-->
* `path` {string}
@@ -22,5 +22,5 @@ path.basename('/foo/bar/baz/asdf/quux.html', '.html');
// 返回: 'quux'
```
-如果 `path` 不是字符串或者给定了 `ext` 且不是字符串,则抛出 [`TypeError`]。
+如果 `path` 不是字符串、或给定了 `ext` 但不是字符串,则抛出 [`TypeError`]。
diff --git a/path/windows_vs_posix.md b/path/windows_vs_posix.md
index 6393b44a..2ec7ce50 100644
--- a/path/windows_vs_posix.md
+++ b/path/windows_vs_posix.md
@@ -1,6 +1,6 @@
-`path` 模块的默认操作因 Node.js 应用程序运行所在的操作系统而异。
-具体来说,当在 Windows 操作系统上运行时,`path` 模块将假定正在使用 Windows 风格的路径。
+`path` 模块的默认操作会因 Node.js 应用程序运行所在的操作系统而异。
+具体来说,当在 Windows 操作系统上运行时,`path` 模块会假定正被使用的是 Windows 风格的路径。
因此,使用 `path.basename()` 可能会在 POSIX 和 Windows 上产生不同的结果:
@@ -18,7 +18,7 @@ path.basename('C:\\temp\\myfile.html');
// 返回: 'myfile.html'
```
-要在任何操作系统上使用 Windows 文件路径时获得一致的结果,则使用 [`path.win32`]:
+如果要在任意操作系统上使用 Windows 文件路径时获得一致的结果,则使用 [`path.win32`]:
在 POSIX 和 Windows 上:
@@ -27,7 +27,7 @@ path.win32.basename('C:\\temp\\myfile.html');
// 返回: 'myfile.html'
```
-要在任何操作系统上使用 POSIX 文件路径时获得一致的结果,则使用 [`path.posix`]:
+如果要在任意操作系统上使用 POSIX 文件路径时获得一致的结果,则使用 [`path.posix`]:
在 POSIX 和 Windows 上:
@@ -36,7 +36,7 @@ path.posix.basename('/tmp/myfile.html');
// 返回: 'myfile.html'
```
-在 Windows 上,Node.js 遵循每个驱动器工作目录的概念。
+在 Windows 上,Node.js 遵循各自驱动器工作目录的理念。
当使用没有反斜杠的驱动器路径时,可以观察到此行为。
例如,`path.resolve('C:\\')` 可能会返回与 `path.resolve('C:')` 不同的结果。
有关详细信息,参阅[此 MSDN 页面][MSDN-Rel-Path]。
diff --git a/process/process_stderr_fd.md b/process/process_stderr_fd.md
new file mode 100644
index 00000000..6781fa02
--- /dev/null
+++ b/process/process_stderr_fd.md
@@ -0,0 +1,7 @@
+
+* {number}
+
+This property refers to the value of underlying file descriptor of
+`process.stderr`. The value is fixed at `2`. In [`Worker`][] threads,
+this field does not exist.
+
diff --git a/process/process_stdin_fd.md b/process/process_stdin_fd.md
new file mode 100644
index 00000000..0ef7738c
--- /dev/null
+++ b/process/process_stdin_fd.md
@@ -0,0 +1,7 @@
+
+* {number}
+
+This property refers to the value of underlying file descriptor of
+`process.stdin`. The value is fixed at `0`. In [`Worker`][] threads,
+this field does not exist.
+
diff --git a/process/process_stdout_fd.md b/process/process_stdout_fd.md
new file mode 100644
index 00000000..2f6cfe75
--- /dev/null
+++ b/process/process_stdout_fd.md
@@ -0,0 +1,7 @@
+
+* {number}
+
+This property refers to the value of underlying file descriptor of
+`process.stdout`. The value is fixed at `1`. In [`Worker`][] threads,
+this field does not exist.
+
diff --git a/readline/rl_cursor.md b/readline/rl_cursor.md
index 45f651d8..4c0fa6f6 100644
--- a/readline/rl_cursor.md
+++ b/readline/rl_cursor.md
@@ -1,5 +1,5 @@
* {number|undefined}
diff --git a/readline/rl_line.md b/readline/rl_line.md
index 151afd04..e6f938c2 100644
--- a/readline/rl_line.md
+++ b/readline/rl_line.md
@@ -1,5 +1,5 @@
* {string|undefined}
diff --git a/report/configuration.md b/report/configuration.md
index 16cb4709..2b8f8fd7 100644
--- a/report/configuration.md
+++ b/report/configuration.md
@@ -57,4 +57,3 @@ NODE_OPTIONS="--experimental-report --report-uncaught-exception \
Specific API documentation can be found under
[`process API documentation`][] section.
-
diff --git a/report/diagnostic_report.md b/report/diagnostic_report.md
index 2703bf89..2949fb6b 100644
--- a/report/diagnostic_report.md
+++ b/report/diagnostic_report.md
@@ -296,6 +296,7 @@ is provided below for reference.
"address": "0x000055fc7b2cb180"
}
],
+ "workers": [],
"environmentVariables": {
"REMOTEHOST": "REMOVED",
"MANPATH": "/opt/rh/devtoolset-3/root/usr/share/man:",
diff --git a/report/interaction_with_workers.md b/report/interaction_with_workers.md
new file mode 100644
index 00000000..636df1d3
--- /dev/null
+++ b/report/interaction_with_workers.md
@@ -0,0 +1,20 @@
+
+
+[`Worker`][] threads can create reports in the same way that the main thread
+does.
+
+Reports will include information on any Workers that are children of the current
+thread as part of the `workers` section, with each Worker generating a report
+in the standard report format.
+
+The thread which is generating the report will wait for the reports from Worker
+threads to finish. However, the latency for this will usually be low, as both
+running JavaScript and the event loop are interrupted to generate the report.
+
+
+
diff --git a/stream/piping_to_writable_streams_from_async_iterators.md b/stream/piping_to_writable_streams_from_async_iterators.md
index 6645f890..34301830 100644
--- a/stream/piping_to_writable_streams_from_async_iterators.md
+++ b/stream/piping_to_writable_streams_from_async_iterators.md
@@ -7,15 +7,33 @@ const finished = util.promisify(stream.finished);
const writable = fs.createWriteStream('./file');
-(async function() {
- for await (const chunk of iterator) {
+function drain(writable) {
+ if (writable.destroyed) {
+ return Promise.reject(new Error('过早关闭'));
+ }
+ return Promise.race([
+ once(writable, 'drain'),
+ once(writable, 'close')
+ .then(() => Promise.reject(new Error('过早关闭')))
+ ]);
+}
+
+async function pump(iterable, writable) {
+ for await (const chunk of iterable) {
// 处理 write() 上的背压。
- if (!writable.write(chunk))
- await once(writable, 'drain');
+ if (!writable.write(chunk)) {
+ await drain(writable);
+ }
}
writable.end();
+}
+
+(async function() {
// 确保完成没有错误。
- await finished(writable);
+ await Promise.all([
+ pump(iterable, writable),
+ finished(writable)
+ ]);
})();
```
@@ -31,7 +49,7 @@ const finished = util.promisify(stream.finished);
const writable = fs.createWriteStream('./file');
(async function() {
- const readable = Readable.from(iterator);
+ const readable = Readable.from(iterable);
readable.pipe(writable);
// 确保完成没有错误。
await finished(writable);
@@ -46,7 +64,7 @@ const pipeline = util.promisify(stream.pipeline);
const writable = fs.createWriteStream('./file');
(async function() {
- const readable = Readable.from(iterator);
+ const readable = Readable.from(iterable);
await pipeline(readable, writable);
})();
```
diff --git a/stream/writable_writev_chunks_callback.md b/stream/writable_writev_chunks_callback.md
index 5272c4d1..a35a7939 100644
--- a/stream/writable_writev_chunks_callback.md
+++ b/stream/writable_writev_chunks_callback.md
@@ -7,7 +7,7 @@
该函数应该由子类实现,且只能被内部的 `Writable` 类的方法调用。
除了在流实现中的 `writable._write()` 之外,还可以实现 `writable._writev()` 方法,其能够一次处理多个数据块。
-如果实现了该方法,调用该方法时会传入当前缓冲在写入队列中的所有数据块。
+如果已实现且之前写入的数据有缓冲,则会调用 `_writev()` 而不是 `_write()`。
`writable._writev()` 方法有下划线前缀,因为它是在定义在类的内部,不应该被用户程序直接调用。
diff --git a/tls/server_addcontext_hostname_context.md b/tls/server_addcontext_hostname_context.md
index acc65de6..90fcf5b1 100644
--- a/tls/server_addcontext_hostname_context.md
+++ b/tls/server_addcontext_hostname_context.md
@@ -2,7 +2,7 @@
added: v0.5.3
-->
-* `hostname` {string} A SNI hostname or wildcard (e.g. `'*'`)
+* `hostname` {string} A SNI host name or wildcard (e.g. `'*'`)
* `context` {Object} An object containing any of the possible properties
from the [`tls.createSecureContext()`][] `options` arguments (e.g. `key`,
`cert`, `ca`, etc).
diff --git a/tls/tls_connect_options_callback.md b/tls/tls_connect_options_callback.md
index 364aa3f7..56154c56 100644
--- a/tls/tls_connect_options_callback.md
+++ b/tls/tls_connect_options_callback.md
@@ -68,7 +68,7 @@ changes:
with optional identity `hint` provided by the server or `null`
in case of TLS 1.3 where `hint` was removed.
It will be necessary to provide a custom `tls.checkServerIdentity()`
- for the connection as the default one will try to check hostname/IP
+ for the connection as the default one will try to check host name/IP
of the server against the certificate but that's not applicable for PSK
because there won't be a certificate present.
More information can be found in the [RFC 4279][].
@@ -88,7 +88,7 @@ changes:
`SNICallback` option to [`tls.createServer()`][].
* `checkServerIdentity(servername, cert)` {Function} A callback function
to be used (instead of the builtin `tls.checkServerIdentity()` function)
- when checking the server's hostname (or the provided `servername` when
+ when checking the server's host name (or the provided `servername` when
explicitly set) against the certificate. This should return an {Error} if
verification fails. The method should return `undefined` if the `servername`
and `cert` are verified.
diff --git a/util/util.md b/util/util.md
index fc4faa47..e9f1d048 100644
--- a/util/util.md
+++ b/util/util.md
@@ -3,7 +3,7 @@
> 稳定性: 2 - 稳定
-`util` 模块主要用于支持 Node.js 内部 API 的需求。
+`util` 模块用于支持 Node.js 内部 API 的需求。
大部分实用工具也可用于应用程序与模块开发者。
使用方法如下:
diff --git a/util/util_log_string.md b/util/util_log_string.md
index 7f4c141b..46db231c 100644
--- a/util/util_log_string.md
+++ b/util/util_log_string.md
@@ -68,6 +68,8 @@ util.log('Timestamped message.');
+
+
diff --git a/util/util_promisify_custom.md b/util/util_promisify_custom.md
index ffbc3d88..1d01a8f2 100644
--- a/util/util_promisify_custom.md
+++ b/util/util_promisify_custom.md
@@ -1,6 +1,23 @@
* {symbol} 可用于声明函数的自定义的 promise 化变量,参阅[自定义的 promise 化函数][Custom promisified functions]。
+除了可以通过 `util.promisify.custom` 进行访问之外,该符号还被[注册为全局]的[global symbol registry],并且可以在任何环境中作为 `Symbol.for('nodejs.util.promisify.custom')` 进行访问。
+
+例如,使用一个接受 `(foo, onSuccessCallback, onErrorCallback)` 的函数:
+
+```js
+const kCustomPromisifiedSymbol = Symbol.for('nodejs.util.promisify.custom');
+
+doSomething[kCustomPromisifiedSymbol] = (foo) => {
+ return new Promise((resolve, reject) => {
+ doSomething(foo, resolve, reject);
+ });
+};
+```
diff --git a/util/util_types_isexternal_value.md b/util/util_types_isexternal_value.md
index 7ea69e84..23d7d878 100644
--- a/util/util_types_isexternal_value.md
+++ b/util/util_types_isexternal_value.md
@@ -7,3 +7,38 @@ added: v10.0.0
Returns `true` if the value is a native `External` value.
+A native `External` value is a special type of object that contains a
+raw C++ pointer (`void*`) for access from native code, and has no other
+properties. Such objects are created either by Node.js internals or native
+addons. In JavaScript, they are [frozen][`Object.freeze()`] objects with a
+`null` prototype.
+
+```c
+#include
+#include
+napi_value result;
+static napi_value MyNapi(napi_env env, napi_callback_info info) {
+ int* raw = (int*) malloc(1024);
+ napi_status status = napi_create_external(env, (void*) raw, NULL, NULL, &result);
+ if (status != napi_ok) {
+ napi_throw_error(env, NULL, "napi_create_external failed");
+ return NULL;
+ }
+ return result;
+}
+...
+DECLARE_NAPI_PROPERTY("myNapi", MyNapi)
+...
+```
+
+```js
+const native = require('napi_addon.node');
+const data = native.myNapi();
+util.types.isExternal(data); // returns true
+util.types.isExternal(0); // returns false
+util.types.isExternal(new String('foo')); // returns false
+```
+
+For further information on `napi_create_external`, refer to
+[`napi_create_external()`][].
+
diff --git a/v8/serialization_api.md b/v8/serialization_api.md
index aeb11e17..53ec8157 100644
--- a/v8/serialization_api.md
+++ b/v8/serialization_api.md
@@ -1,5 +1,7 @@
The serialization API provides means of serializing JavaScript values in a way
that is compatible with the [HTML structured clone algorithm][].
+
The format is backward-compatible (i.e. safe to store to disk).
+Equal JavaScript values may result in different serialized output.
diff --git a/vm/script_runincontext_contextifiedobject_options.md b/vm/script_runincontext_contextifiedobject_options.md
index c231c8d3..28981f4e 100644
--- a/vm/script_runincontext_contextifiedobject_options.md
+++ b/vm/script_runincontext_contextifiedobject_options.md
@@ -34,9 +34,8 @@ for (let i = 0; i < 10; ++i) {
script.runInContext(context);
}
-console.log(util.inspect(context));
-
-// { animal: 'cat', count: 12, name: 'kitty' }
+console.log(context);
+// 打印: { animal: 'cat', count: 12, name: 'kitty' }
```
使用 `timeout` 或者 `breakOnSigint` 选项会导致若干新的事件循环以及对应的线程,这有一个非零的性能消耗。
diff --git a/vm/script_runinnewcontext_contextobject_options.md b/vm/script_runinnewcontext_contextobject_options.md
index 8c3ca38e..1d3220df 100644
--- a/vm/script_runinnewcontext_contextobject_options.md
+++ b/vm/script_runinnewcontext_contextobject_options.md
@@ -38,8 +38,7 @@ contexts.forEach((context) => {
script.runInNewContext(context);
});
-console.log(util.inspect(contexts));
-
-// [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }]
+console.log(contexts);
+// 打印: [{ globalVar: 'set' }, { globalVar: 'set' }, { globalVar: 'set' }]
```
diff --git a/vm/vm_createcontext_contextobject_options.md b/vm/vm_createcontext_contextobject_options.md
index 9ec4ef4c..2b754fe8 100644
--- a/vm/vm_createcontext_contextobject_options.md
+++ b/vm/vm_createcontext_contextobject_options.md
@@ -35,9 +35,11 @@ vm.createContext(context);
vm.runInContext('globalVar *= 2;', context);
-console.log(util.inspect(context)); // { globalVar: 2 }
+console.log(context);
+// 打印: { globalVar: 2 }
-console.log(util.inspect(globalVar)); // 3
+console.log(global.globalVar);
+// 打印: 3
```
如果未提供 `contextObject`(或者传入`undefined`),那么会返回一个全新的空的[上下文隔离化][contextified]对象。
diff --git a/vm/vm_runincontext_code_contextifiedobject_options.md b/vm/vm_runincontext_code_contextifiedobject_options.md
index b08c0751..1eb27150 100644
--- a/vm/vm_runincontext_code_contextifiedobject_options.md
+++ b/vm/vm_runincontext_code_contextifiedobject_options.md
@@ -48,8 +48,7 @@ vm.createContext(contextObject);
for (let i = 0; i < 10; ++i) {
vm.runInContext('globalVar *= 2;', contextObject);
}
-console.log(util.inspect(contextObject));
-
-// { globalVar: 1024 }
+console.log(contextObject);
+// 打印: { globalVar: 1024 }
```
diff --git a/vm/vm_runinnewcontext_code_contextobject_options.md b/vm/vm_runinnewcontext_code_contextobject_options.md
index 9ece22a4..8bfb7d7f 100644
--- a/vm/vm_runinnewcontext_code_contextobject_options.md
+++ b/vm/vm_runinnewcontext_code_contextobject_options.md
@@ -56,8 +56,7 @@ const contextObject = {
};
vm.runInNewContext('count += 1; name = "kitty"', contextObject);
-console.log(util.inspect(contextObject));
-
-// { animal: 'cat', count: 3, name: 'kitty' }
+console.log(contextObject);
+// 打印: { animal: 'cat', count: 3, name: 'kitty' }
```
diff --git a/vm/vm_runinthiscontext_code_options.md b/vm/vm_runinthiscontext_code_options.md
index ce62dc86..0ed7c960 100644
--- a/vm/vm_runinthiscontext_code_options.md
+++ b/vm/vm_runinthiscontext_code_options.md
@@ -42,15 +42,12 @@ const vm = require('vm');
let localVar = 'initial value';
const vmResult = vm.runInThisContext('localVar = "vm";');
-console.log('vmResult:', vmResult);
-console.log('localVar:', localVar);
+console.log(`vmResult: '${vmResult}', localVar: '${localVar}'`);
+// 打印: vmResult: 'vm', localVar: 'initial value'
const evalResult = eval('localVar = "eval";');
-console.log('evalResult:', evalResult);
-console.log('localVar:', localVar);
-
-// vmResult: 'vm', localVar: 'initial value'
-// evalResult: 'eval', localVar: 'eval'
+console.log(`evalResult: '${evalResult}', localVar: '${localVar}'`);
+// 打印: evalResult: 'eval', localVar: 'eval'
```
正因 `vm.runInThisContext()` 无法获取本地作用域,故 `localVar` 的值不变。
diff --git a/worker_threads/event_exit.md b/worker_threads/event_exit.md
index 4b8cc9ee..0d20d45d 100644
--- a/worker_threads/event_exit.md
+++ b/worker_threads/event_exit.md
@@ -9,3 +9,5 @@ exited by calling [`process.exit()`][], the `exitCode` parameter will be the
passed exit code. If the worker was terminated, the `exitCode` parameter will
be `1`.
+This is the final event emitted by any `Worker` instance.
+
diff --git a/worker_threads/event_message_1.md b/worker_threads/event_message_1.md
index ae982f47..876a94dc 100644
--- a/worker_threads/event_message_1.md
+++ b/worker_threads/event_message_1.md
@@ -8,3 +8,6 @@ The `'message'` event is emitted when the worker thread has invoked
[`require('worker_threads').parentPort.postMessage()`][].
See the [`port.on('message')`][] event for more details.
+All messages sent from the worker thread will be emitted before the
+[`'exit'` event][] is emitted on the `Worker` object.
+
diff --git a/worker_threads/worker_threads.md b/worker_threads/worker_threads.md
index b348e0e0..7b1db23e 100644
--- a/worker_threads/worker_threads.md
+++ b/worker_threads/worker_threads.md
@@ -48,4 +48,8 @@ if (isMainThread) {
否则,创建工作线程的开销可能会超出其收益。
当实现工作线程池时,可使用 [`AsyncResource`] API 来通知诊断的工具(例如为了提供异步的堆栈跟踪)有关任务及其结果之间的相关性。
+有关示例的实现,请参阅 `async_hooks` 文档中的[“为 `Worker` 线程池使用 `AsyncResource`”][async-resource-worker-pool]。
+
+默认情况下,工作线程继承非特定于进程的选项。
+请参阅[工作线程的构造函数选项][`Worker constructor options`],以了解如何自定义工作线程的选项,特别是 `argv` 和 `execArgv` 选项。
diff --git a/worker_threads/worker_unref.md b/worker_threads/worker_unref.md
index 7f76ff5a..ae72e504 100644
--- a/worker_threads/worker_unref.md
+++ b/worker_threads/worker_unref.md
@@ -48,6 +48,8 @@ active handle in the event system. If the worker is already `unref()`ed calling
+
+
diff --git a/zlib/class_options.md b/zlib/class_options.md
index afa991ef..c5e2b070 100644
--- a/zlib/class_options.md
+++ b/zlib/class_options.md
@@ -15,7 +15,7 @@ changes:
每一个类都有一个 `options` 对象。
-所有的选项都是可选的。
+所有的选项都不是必需的。
注意一些选项只与压缩相关,会被解压类忽视。
diff --git a/zlib/compressing_http_requests_and_responses.md b/zlib/compressing_http_requests_and_responses.md
index 91e99332..edcfc7e9 100644
--- a/zlib/compressing_http_requests_and_responses.md
+++ b/zlib/compressing_http_requests_and_responses.md
@@ -13,6 +13,8 @@ HTTP 的 [`Accept-Encoding`] 消息头用来标记客户端接受的压缩编码
const zlib = require('zlib');
const http = require('http');
const fs = require('fs');
+const { pipeline } = require('stream');
+
const request = http.get({ host: 'example.com',
path: '/',
port: 80,
@@ -20,19 +22,26 @@ const request = http.get({ host: 'example.com',
request.on('response', (response) => {
const output = fs.createWriteStream('example.com_index.html');
+ const onError = (err) => {
+ if (err) {
+ console.error('发生错误:', err);
+ process.exitCode = 1;
+ }
+ };
+
switch (response.headers['content-encoding']) {
case 'br':
- response.pipe(zlib.createBrotliDecompress()).pipe(output);
+ pipeline(response, zlib.createBrotliDecompress(), output, onError);
break;
// 或者, 只是使用 zlib.createUnzip() 方法去处理这两种情况:
case 'gzip':
- response.pipe(zlib.createGunzip()).pipe(output);
+ pipeline(response, zlib.createGunzip(), output, onError);
break;
case 'deflate':
- response.pipe(zlib.createInflate()).pipe(output);
+ pipeline(response, zlib.createInflate(), outout, onError);
break;
default:
- response.pipe(output);
+ pipeline(response, output, onError);
break;
}
});
@@ -45,29 +54,42 @@ request.on('response', (response) => {
const zlib = require('zlib');
const http = require('http');
const fs = require('fs');
+const { pipeline } = require('stream');
+
http.createServer((request, response) => {
const raw = fs.createReadStream('index.html');
// 存储资源的压缩版本和未压缩版本。
- response.setHeader('Vary: Accept-Encoding');
+ response.setHeader('Vary', 'Accept-Encoding');
let acceptEncoding = request.headers['accept-encoding'];
if (!acceptEncoding) {
acceptEncoding = '';
}
+ const onError = (err) => {
+ if (err) {
+ // 如果发生错误,则我们将会无能为力,
+ // 因为服务器已经发送了 200 响应码,
+ // 并且已经向客户端发送了一些数据。
+ // 我们能做的最好就是立即终止响应并记录错误。
+ response.end();
+ console.error('发生错误:', err);
+ }
+ };
+
// 注意:这不是一个合适的 accept-encoding 解析器。
// 查阅 https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.3
if (/\bdeflate\b/.test(acceptEncoding)) {
response.writeHead(200, { 'Content-Encoding': 'deflate' });
- raw.pipe(zlib.createDeflate()).pipe(response);
+ pipeline(raw, zlib.createDeflate(), response, onError);
} else if (/\bgzip\b/.test(acceptEncoding)) {
response.writeHead(200, { 'Content-Encoding': 'gzip' });
- raw.pipe(zlib.createGzip()).pipe(response);
+ pipeline(raw, zlib.createGzip(), response, onError);
} else if (/\bbr\b/.test(acceptEncoding)) {
response.writeHead(200, { 'Content-Encoding': 'br' });
- raw.pipe(zlib.createBrotliCompress()).pipe(response);
+ pipeline(raw, zlib.createBrotliCompress(), response, onError);
} else {
response.writeHead(200, {});
- raw.pipe(response);
+ pipeline(raw, response, onError);
}
}).listen(1337);
```
@@ -84,11 +106,11 @@ zlib.unzip(
// 对于 Brotli,等效的是 zlib.constants.BROTLI_OPERATION_FLUSH。
{ finishFlush: zlib.constants.Z_SYNC_FLUSH },
(err, buffer) => {
- if (!err) {
- console.log(buffer.toString());
- } else {
- // 错误处理
+ if (err) {
+ console.error('发生错误:', err);
+ process.exitCode = 1;
}
+ console.log(buffer.toString());
});
```
diff --git a/zlib/flushing.md b/zlib/flushing.md
index 958dbdee..19e6616c 100644
--- a/zlib/flushing.md
+++ b/zlib/flushing.md
@@ -6,14 +6,27 @@
```js
const zlib = require('zlib');
const http = require('http');
+const { pipeline } = require('stream');
http.createServer((request, response) => {
// 为了简单起见,省略了对 Accept-Encoding 的检测。
response.writeHead(200, { 'content-encoding': 'gzip' });
const output = zlib.createGzip();
- output.pipe(response);
+ let i;
- setInterval(() => {
+ pipeline(output, response, (err) => {
+ if (err) {
+ // 如果发生错误,则我们将会无能为力,
+ // 因为服务器已经发送了 200 响应码,
+ // 并且已经向客户端发送了一些数据。
+ // 我们能做的最好就是立即终止响应并记录错误。
+ clearInterval(i);
+ response.end();
+ console.error('发生错误:', err);
+ }
+ });
+
+ i = setInterval(() => {
output.write(`The current time is ${Date()}\n`, () => {
// 数据已经传递给了 zlib,但压缩算法看能已经决定缓存数据以便得到更高的压缩效率。
// 一旦客户端准备接收数据,调用 .flush() 将会使数据可用。
diff --git a/zlib/threadpool_usage.md b/zlib/threadpool_usage.md
deleted file mode 100644
index 7a0464a5..00000000
--- a/zlib/threadpool_usage.md
+++ /dev/null
@@ -1,4 +0,0 @@
-
-除显式同步的 API 之外,所有 zlib API 均使用 libuv 的线程池。
-这可能会在某些应用程序中产生意外的效果,例如性能不佳(可以通过调整[池的大小][pool size]来缓和)和/或无法恢复的灾难性内存碎片。
-
diff --git a/zlib/threadpool_usage_and_performance_considerations.md b/zlib/threadpool_usage_and_performance_considerations.md
new file mode 100644
index 00000000..734fab55
--- /dev/null
+++ b/zlib/threadpool_usage_and_performance_considerations.md
@@ -0,0 +1,24 @@
+
+
+除显式同步的 API 之外,所有 `zlib` API 均使用 Node.js 内部的线程池。
+这可能会在某些应用程序中产生意外的效果或性能限制。
+
+同时创建和使用大量的 zlib 对象可能会导致明显的内存碎片。
+
+
+```js
+const zlib = require('zlib');
+
+const payload = Buffer.from('这是一些数据');
+
+// 警告:请勿这样做!
+for (let i = 0; i < 30000; ++i) {
+ zlib.deflate(payload, (err, buffer) => {});
+}
+```
+
+在前面的示例中,同时创建了 30,000 个 deflate 实例。
+由于某些操作系统处理内存分配和释放的方式,因此可能会导致内存碎片严重。
+
+强烈建议对压缩操作的结果进行缓存,以避免重复工作。
+
diff --git a/zlib/zlib.md b/zlib/zlib.md
index e1b881e0..fc122952 100644
--- a/zlib/zlib.md
+++ b/zlib/zlib.md
@@ -3,50 +3,89 @@
> 稳定性: 2 - 稳定
-`zlib` 模块提供通过 Gzip 和 Deflate/Inflate 实现的压缩功能,Brotli 也是如此。
+`zlib` 模块提供通过 Gzip、Deflate/Inflate、和 Brotli 实现的压缩功能。
+
可以通过这样使用它:
```js
const zlib = require('zlib');
```
-压缩或者解压数据流(例如一个文件)通过 `zlib` 流将源数据流传输到目标流中来完成。
+压缩和解压都是围绕 Node.js 的 [Streams API] 构建的。
+
+压缩或者解压流(例如一个文件)通过 `zlib` `Transform` 流将源数据流传输到目标流中来完成。
```js
-const gzip = zlib.createGzip();
-const fs = require('fs');
-const inp = fs.createReadStream('input.txt');
-const out = fs.createWriteStream('input.txt.gz');
-
-inp.pipe(gzip)
- .on('error', () => {
- // 处理错误
- })
- .pipe(out)
- .on('error', () => {
- // 处理错误
+const { createGzip } = require('zlib');
+const { pipeline } = require('stream');
+const {
+ createReadStream,
+ createWriteStream
+} = require('fs');
+
+const gzip = createGzip();
+const source = createReadStream('input.txt');
+const destination = createWriteStream('input.txt.gz');
+
+pipeline(source, gzip, destination, (err) => {
+ if (err) {
+ console.error('发生错误:', err);
+ process.exitCode = 1;
+ }
+});
+
+// 或 Promise 化:
+
+const { promisify } = require('util');
+const pipe = promisify(pipeline);
+
+async function do_gzip(input, output) {
+ const gzip = createGzip();
+ const source = createReadStream(input);
+ const destination = createWriteStream(output);
+ await pipe(source, gzip, destination);
+}
+
+do_gzip('input.txt', 'input.txt.gz')
+ .catch((err) => {
+ console.error('发生错误:', err);
+ process.exitCode = 1;
});
```
数据的压缩或解压缩也可以只用一个步骤完成:
```js
+const { deflate, unzip } = require('zlib');
+
const input = '.................................';
-zlib.deflate(input, (err, buffer) => {
- if (!err) {
- console.log(buffer.toString('base64'));
- } else {
- // 处理错误
+deflate(input, (err, buffer) => {
+ if (err) {
+ console.error('发生错误:', err);
+ process.exitCode = 1;
}
+ console.log(buffer.toString('base64'));
});
const buffer = Buffer.from('eJzT0yMAAGTvBe8=', 'base64');
-zlib.unzip(buffer, (err, buffer) => {
- if (!err) {
- console.log(buffer.toString());
- } else {
- // 处理错误
+unzip(buffer, (err, buffer) => {
+ if (err) {
+ console.error('发生错误:', err);
+ process.exitCode = 1;
}
+ console.log(buffer.toString());
});
+
+// 或 Promise 化:
+
+const { promisify } = require('util');
+const do_unzip = promisify(unzip);
+
+do_unzip(buffer)
+ .then((buf) => console.log(buf.toString()))
+ .catch((err) => {
+ console.error('发生错误:', err);
+ process.exitCode = 1;
+ });
```