- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- env 环境变量
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
Node.js v22.22.0 文档
- Node.js v22.22.0
-
目录
- V8
v8.cachedDataVersionTag()v8.getHeapCodeStatistics()v8.getHeapSnapshot([options])v8.getHeapSpaceStatistics()v8.getHeapStatistics()v8.getCppHeapStatistics([detailLevel])v8.queryObjects(ctor[, options])v8.setFlagsFromString(flags)v8.stopCoverage()v8.takeCoverage()v8.writeHeapSnapshot([filename[,options]])v8.setHeapSnapshotNearHeapLimit(limit)- 序列化 API
v8.serialize(value)v8.deserialize(buffer)- 类:
v8.Serializernew Serializer()serializer.writeHeader()serializer.writeValue(value)serializer.releaseBuffer()serializer.transferArrayBuffer(id, arrayBuffer)serializer.writeUint32(value)serializer.writeUint64(hi, lo)serializer.writeDouble(value)serializer.writeRawBytes(buffer)serializer._writeHostObject(object)serializer._getDataCloneError(message)serializer._getSharedArrayBufferId(sharedArrayBuffer)serializer._setTreatArrayBufferViewsAsHostObjects(flag)
- 类:
v8.Deserializernew Deserializer(buffer)deserializer.readHeader()deserializer.readValue()deserializer.transferArrayBuffer(id, arrayBuffer)deserializer.getWireFormatVersion()deserializer.readUint32()deserializer.readUint64()deserializer.readDouble()deserializer.readRawBytes(length)deserializer._readHostObject()
- 类:
v8.DefaultSerializer - 类:
v8.DefaultDeserializer
- Promise 钩子
- 启动快照 API
- 类:
v8.GCProfiler v8.isStringOneByteRepresentation(content)
- V8
-
导航
- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- Corepack 核心包
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- env 环境变量
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
- 其他版本
V8#>
源代码: lib/v8.js
node:v8 模块提供了特定于内置在 Node.js 二进制文件中的 V8 版本的 API。可以通过以下方式访问:
【The node:v8 module exposes APIs that are specific to the version of V8
built into the Node.js binary. It can be accessed using:】
const v8 = require('node:v8');
v8.cachedDataVersionTag()#>
- 返回:<integer>
返回一个整数,表示从 V8 版本、命令行标志和检测到的 CPU 功能派生的版本标签。这对于确定某个 vm.Script cachedData 缓冲区是否与此 V8 实例兼容非常有用。
【Returns an integer representing a version tag derived from the V8 version,
command-line flags, and detected CPU features. This is useful for determining
whether a vm.Script cachedData buffer is compatible with this instance
of V8.】
console.log(v8.cachedDataVersionTag()); // 3947234607
// The value returned by v8.cachedDataVersionTag() is derived from the V8
// version, command-line flags, and detected CPU features. Test that the value
// does indeed update when flags are toggled.
v8.setFlagsFromString('--allow_natives_syntax');
console.log(v8.cachedDataVersionTag()); // 183726201
v8.getHeapCodeStatistics()#>
- 返回:<Object>
获取有关堆中代码及其元数据的统计信息,请参见 V8 GetHeapCodeAndMetadataStatistics API。返回一个具有以下属性的对象:
【Get statistics about code and its metadata in the heap, see V8
GetHeapCodeAndMetadataStatistics API. Returns an object with the
following properties:】
code_and_metadata_size<number>bytecode_and_metadata_size<number>external_script_source_size<number>cpu_profiler_metadata_size<number>
{
code_and_metadata_size: 212208,
bytecode_and_metadata_size: 161368,
external_script_source_size: 1410794,
cpu_profiler_metadata_size: 0,
}
v8.getHeapSnapshot([options])#>
options<Object>- 返回:<stream.Readable> 一个包含 V8 堆快照的可读流。
生成当前 V8 堆的快照,并返回一个可读取流,可用于读取 JSON 序列化表示形式。此 JSON 流格式旨在与诸如 Chrome DevTools 之类的工具一起使用。JSON 模式未记录,并且特定于 V8 引擎。因此,该模式可能会随着 V8 的不同版本而更改。
【Generates a snapshot of the current V8 heap and returns a Readable Stream that may be used to read the JSON serialized representation. This JSON stream format is intended to be used with tools such as Chrome DevTools. The JSON schema is undocumented and specific to the V8 engine. Therefore, the schema may change from one version of V8 to the next.】
创建堆快照时需要的内存大约是创建快照时堆大小的两倍。这会导致 OOM 杀手可能终止该进程的风险。
【Creating a heap snapshot requires memory about twice the size of the heap at the time the snapshot is created. This results in the risk of OOM killers terminating the process.】
生成快照是一个同步操作,会根据堆大小阻塞事件循环一段时间。
【Generating a snapshot is a synchronous operation which blocks the event loop for a duration depending on the heap size.】
// Print heap snapshot to the console
const v8 = require('node:v8');
const stream = v8.getHeapSnapshot();
stream.pipe(process.stdout);
v8.getHeapSpaceStatistics()#>
- 返回:对象[]
返回关于 V8 堆空间的统计信息,即构成 V8 堆的各个段。堆空间的顺序或堆空间的可用性都无法保证,因为这些统计信息是通过 V8 的 GetHeapSpaceStatistics 函数提供的,并且可能会随着 V8 版本的不同而变化。
【Returns statistics about the V8 heap spaces, i.e. the segments which make up
the V8 heap. Neither the ordering of heap spaces, nor the availability of a
heap space can be guaranteed as the statistics are provided via the V8
GetHeapSpaceStatistics function and may change from one V8 version to the
next.】
返回的值是包含以下属性的对象数组
【The value returned is an array of objects containing the following properties:】
space_name<string>space_size<number>space_used_size<number>space_available_size<number>physical_space_size<number>
[
{
"space_name": "new_space",
"space_size": 2063872,
"space_used_size": 951112,
"space_available_size": 80824,
"physical_space_size": 2063872
},
{
"space_name": "old_space",
"space_size": 3090560,
"space_used_size": 2493792,
"space_available_size": 0,
"physical_space_size": 3090560
},
{
"space_name": "code_space",
"space_size": 1260160,
"space_used_size": 644256,
"space_available_size": 960,
"physical_space_size": 1260160
},
{
"space_name": "map_space",
"space_size": 1094160,
"space_used_size": 201608,
"space_available_size": 0,
"physical_space_size": 1094160
},
{
"space_name": "large_object_space",
"space_size": 0,
"space_used_size": 0,
"space_available_size": 1490980608,
"physical_space_size": 0
}
]
v8.getHeapStatistics()#>
- 返回:<Object>
返回具有以下属性的对象:
【Returns an object with the following properties:】
total_heap_size<number>total_heap_size_executable<number>total_physical_size<number>total_available_size<number>used_heap_size<number>heap_size_limit<number>malloced_memory<number>peak_malloced_memory<number>does_zap_garbage<number>number_of_native_contexts<number>number_of_detached_contexts<number>total_global_handles_size<number>used_global_handles_size<number>external_memory<number>
total_heap_size total_heap_size 的值是 V8 为堆分配的字节数。如果 used_heap 需要更多内存,这个值可能会增长。
total_heap_size_executable total_heap_size_executable 的值是堆中可以包含可执行代码的部分,以字节为单位。这包括 JIT 编译的代码所使用的内存以及必须保持可执行的任何内存。
total_physical_size total_physical_size 的值是 V8 堆实际使用的物理内存(以字节为单位)。这是已提交(或正在使用)的内存量,而不是保留的内存量。
total_available_size total_available_size 的值是可分配给 V8 堆的内存字节数。该值表示 V8 在超过堆限制之前还能使用的内存量。
used_heap_size used_heap_size 的值是当前 V8 的 JavaScript 对象正在使用的字节数。这是实际使用的内存,不包括已分配但尚未使用的内存。
heap_size_limit heap_size_limit 的值是 V8 堆的最大大小,以字节为单位(可以是默认限制,由系统资源决定,或者是传递给 --max_old_space_size 选项的值)。
malloced_memory malloced_memory 的值是 V8 通过 malloc 分配的字节数。
peak_malloced_memory peak_malloced_memory 的值是在进程生命周期内 V8 通过 malloc 分配的字节数峰值。
does_zap_garbage 是一个 0/1 布尔值,用于表示是否启用了 --zap_code_space 选项。这会让 V8 用特定位模式覆盖堆中的垃圾。RSS 占用(常驻集大小)会变大,因为它会不断访问所有堆页,从而使这些页面不太可能被操作系统换出。
number_of_native_contexts native_context 的值是当前活动的顶层上下文数量。随着时间的增加,这个数量的增加表明存在内存泄漏。
number_of_detached_contexts detached_context 的值是已分离但尚未被垃圾回收的上下文数量。该数值不为零表示可能存在内存泄漏。
total_global_handles_size total_global_handles_size 的值是 V8 全局句柄的总内存大小。
used_global_handles_size used_global_handles_size 的值是 V8 全局句柄使用的内存大小。
external_memory 外部内存的值是数组缓冲区和外部字符串的内存大小。
{
total_heap_size: 7326976,
total_heap_size_executable: 4194304,
total_physical_size: 7326976,
total_available_size: 1152656,
used_heap_size: 3476208,
heap_size_limit: 1535115264,
malloced_memory: 16384,
peak_malloced_memory: 1127496,
does_zap_garbage: 0,
number_of_native_contexts: 1,
number_of_detached_contexts: 0,
total_global_handles_size: 8192,
used_global_handles_size: 3296,
external_memory: 318824
}
v8.getCppHeapStatistics([detailLevel])#>
使用 V8 CollectStatistics() 函数获取关于内存消耗和利用率的 Cpp堆 统计信息,该函数可能会随 V8 版本的不同而变化。
【Retrieves CppHeap statistics regarding memory consumption and
utilization using the V8 CollectStatistics() function which
may change from one V8 version to the
next.】
detailLevel<string> | <undefined>: 默认值:'detailed'。 指定返回统计信息的详细程度。 可接受的值有:'brief':简要统计仅包含整个堆的顶层已分配和已使用内存统计信息。'detailed':详细统计信息还包括每个空间和页面的细分,以及空闲列表统计和对象类型直方图。
它返回一个结构类似于 cppgc::HeapStatistics 对象的对象。有关该对象属性的更多信息,请参阅 V8 文档。
【It returns an object with a structure similar to the
cppgc::HeapStatistics object. See the V8 documentation
for more information about the properties of the object.】
// Detailed
({
committed_size_bytes: 131072,
resident_size_bytes: 131072,
used_size_bytes: 152,
space_statistics: [
{
name: 'NormalPageSpace0',
committed_size_bytes: 0,
resident_size_bytes: 0,
used_size_bytes: 0,
page_stats: [{}],
free_list_stats: {},
},
{
name: 'NormalPageSpace1',
committed_size_bytes: 131072,
resident_size_bytes: 131072,
used_size_bytes: 152,
page_stats: [{}],
free_list_stats: {},
},
{
name: 'NormalPageSpace2',
committed_size_bytes: 0,
resident_size_bytes: 0,
used_size_bytes: 0,
page_stats: [{}],
free_list_stats: {},
},
{
name: 'NormalPageSpace3',
committed_size_bytes: 0,
resident_size_bytes: 0,
used_size_bytes: 0,
page_stats: [{}],
free_list_stats: {},
},
{
name: 'LargePageSpace',
committed_size_bytes: 0,
resident_size_bytes: 0,
used_size_bytes: 0,
page_stats: [{}],
free_list_stats: {},
},
],
type_names: [],
detail_level: 'detailed',
});
// Brief
({
committed_size_bytes: 131072,
resident_size_bytes: 131072,
used_size_bytes: 128864,
space_statistics: [],
type_names: [],
detail_level: 'brief',
});
v8.queryObjects(ctor[, options])#>
ctor<Function> 该构造函数可用于在原型链上搜索,以便过滤堆中的目标对象。options<undefined> | <Object>format<string> 如果是'count',则返回匹配对象的数量。如果是'summary',则返回包含匹配对象摘要字符串的数组。
- 返回值:{number|Array
}
这类似于 Chromium DevTools 控制台提供的 queryObjects() 控制台 API。它可用于在完整垃圾回收后搜索在堆中具有匹配构造函数原型链的对象,这对于内存泄漏回归测试非常有用。为了避免意外结果,用户应避免在他们无法控制实现的构造函数上使用此 API,或在应用中可能被其他方调用的构造函数上使用此 API。
【This is similar to the queryObjects() console API provided by the
Chromium DevTools console. It can be used to search for objects that
have the matching constructor on its prototype chain in the heap after
a full garbage collection, which can be useful for memory leak
regression tests. To avoid surprising results, users should avoid using
this API on constructors whose implementation they don't control, or on
constructors that can be invoked by other parties in the application.】
为了避免意外泄露,此 API 不会返回找到的对象的原始引用。默认情况下,它会返回找到的对象数量。如果 options.format 为 'summary',它会返回一个包含每个对象简要字符串表示的数组。此 API 提供的可见性类似于堆快照所提供的,而用户可以节省序列化和解析的开销,并在搜索过程中直接过滤目标对象。
【To avoid accidental leaks, this API does not return raw references to
the objects found. By default, it returns the count of the objects
found. If options.format is 'summary', it returns an array
containing brief string representations for each object. The visibility
provided in this API is similar to what the heap snapshot provides,
while users can save the cost of serialization and parsing and directly
filter the target objects during the search.】
只有在当前执行上下文中创建的对象才会包含在结果中。
【Only objects created in the current execution context are included in the results.】
const { queryObjects } = require('node:v8');
class A { foo = 'bar'; }
console.log(queryObjects(A)); // 0
const a = new A();
console.log(queryObjects(A)); // 1
// [ "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }));
class B extends A { bar = 'qux'; }
const b = new B();
console.log(queryObjects(B)); // 1
// [ "B { foo: 'bar', bar: 'qux' }" ]
console.log(queryObjects(B, { format: 'summary' }));
// Note that, when there are child classes inheriting from a constructor,
// the constructor also shows up in the prototype chain of the child
// classes's prototype, so the child classes's prototype would also be
// included in the result.
console.log(queryObjects(A)); // 3
// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }));import { queryObjects } from 'node:v8';
class A { foo = 'bar'; }
console.log(queryObjects(A)); // 0
const a = new A();
console.log(queryObjects(A)); // 1
// [ "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }));
class B extends A { bar = 'qux'; }
const b = new B();
console.log(queryObjects(B)); // 1
// [ "B { foo: 'bar', bar: 'qux' }" ]
console.log(queryObjects(B, { format: 'summary' }));
// Note that, when there are child classes inheriting from a constructor,
// the constructor also shows up in the prototype chain of the child
// classes's prototype, so the child classes's prototype would also be
// included in the result.
console.log(queryObjects(A)); // 3
// [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
console.log(queryObjects(A, { format: 'summary' }));
v8.setFlagsFromString(flags)#>
flags<string>
v8.setFlagsFromString() 方法可用于以编程方式设置 V8 命令行标志。使用此方法时应谨慎。在虚拟机启动后更改设置可能导致不可预测的行为,包括崩溃和数据丢失;或者它可能根本不会产生任何效果。
【The v8.setFlagsFromString() method can be used to programmatically set
V8 command-line flags. This method should be used with care. Changing settings
after the VM has started may result in unpredictable behavior, including
crashes and data loss; or it may simply do nothing.】
可以通过运行 node --v8-options 来确定某个版本的 Node.js 可用的 V8 选项。
【The V8 options available for a version of Node.js may be determined by running
node --v8-options.】
用法:
【Usage:】
// Print GC events to stdout for one minute.
const v8 = require('node:v8');
v8.setFlagsFromString('--trace_gc');
setTimeout(() => { v8.setFlagsFromString('--notrace_gc'); }, 60e3);
v8.stopCoverage()#>
v8.stopCoverage() 方法允许用户停止由 NODE_V8_COVERAGE 启动的覆盖率收集,这样 V8 就可以释放执行计数记录并优化代码。如果用户希望按需收集覆盖率,可以与 v8.takeCoverage() 一起使用。
【The v8.stopCoverage() method allows the user to stop the coverage collection
started by NODE_V8_COVERAGE, so that V8 can release the execution count
records and optimize code. This can be used in conjunction with
v8.takeCoverage() if the user wants to collect the coverage on demand.】
v8.takeCoverage()#>
v8.takeCoverage() 方法允许用户按需将 NODE_V8_COVERAGE 开始的覆盖率写入磁盘。该方法可以在进程生命周期内多次调用。每次调用时,执行计数器都会被重置,一个新的覆盖率报告将被写入 NODE_V8_COVERAGE 指定的目录。
【The v8.takeCoverage() method allows the user to write the coverage started by
NODE_V8_COVERAGE to disk on demand. This method can be invoked multiple
times during the lifetime of the process. Each time the execution counter will
be reset and a new coverage report will be written to the directory specified
by NODE_V8_COVERAGE.】
当进程即将退出时,除非在进程退出前调用 v8.stopCoverage(),否则最后一次覆盖率仍会写入磁盘。
【When the process is about to exit, one last coverage will still be written to
disk unless v8.stopCoverage() is invoked before the process exits.】
v8.writeHeapSnapshot([filename[,options]])#>
filename<string> 要保存 V8 堆快照的文件路径。如果未指定,将生成一个符合模式'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot'的文件名,其中{pid}是 Node.js 进程的 PID,{thread_id}在从主 Node.js 线程调用writeHeapSnapshot()时为0,或者为工作线程的 ID。options<Object>- 返回值:<string> 快照保存的文件名。
生成当前 V8 堆的快照并将其写入 JSON 文件。该文件旨在与 Chrome 开发者工具等工具一起使用。JSON 模式未记录,并且特定于 V8 引擎,可能会随着 V8 的不同版本而变化。
【Generates a snapshot of the current V8 heap and writes it to a JSON file. This file is intended to be used with tools such as Chrome DevTools. The JSON schema is undocumented and specific to the V8 engine, and may change from one version of V8 to the next.】
堆快照特定于单个 V8 隔离区。使用 工作线程 时,从主线程生成的堆快照将不包含任何关于工作线程的信息,反之亦然。
【A heap snapshot is specific to a single V8 isolate. When using worker threads, a heap snapshot generated from the main thread will not contain any information about the workers, and vice versa.】
创建堆快照时需要的内存大约是创建快照时堆大小的两倍。这会导致 OOM 杀手可能终止该进程的风险。
【Creating a heap snapshot requires memory about twice the size of the heap at the time the snapshot is created. This results in the risk of OOM killers terminating the process.】
生成快照是一个同步操作,会根据堆大小阻塞事件循环一段时间。
【Generating a snapshot is a synchronous operation which blocks the event loop for a duration depending on the heap size.】
const { writeHeapSnapshot } = require('node:v8');
const {
Worker,
isMainThread,
parentPort,
} = require('node:worker_threads');
if (isMainThread) {
const worker = new Worker(__filename);
worker.once('message', (filename) => {
console.log(`worker heapdump: ${filename}`);
// Now get a heapdump for the main thread.
console.log(`main thread heapdump: ${writeHeapSnapshot()}`);
});
// Tell the worker to create a heapdump.
worker.postMessage('heapdump');
} else {
parentPort.once('message', (message) => {
if (message === 'heapdump') {
// Generate a heapdump for the worker
// and return the filename to the parent.
parentPort.postMessage(writeHeapSnapshot());
}
});
}
v8.setHeapSnapshotNearHeapLimit(limit)#>
limit<integer>
如果命令行中已经设置了 --heapsnapshot-near-heap-limit,或者 API 被调用超过一次,该 API 将不会执行任何操作。limit 必须是正整数。有关更多信息,请参阅 --heapsnapshot-near-heap-limit。
【The API is a no-op if --heapsnapshot-near-heap-limit is already set from the
command line or the API is called more than once. limit must be a positive
integer. See --heapsnapshot-near-heap-limit for more information.】
序列化 API#>
【Serialization API】
序列化 API 提供了一种以与 HTML 结构化克隆算法 兼容的方式序列化 JavaScript 值的方法。
【The serialization API provides means of serializing JavaScript values in a way that is compatible with the HTML structured clone algorithm.】
该格式向后兼容(即可安全存储到磁盘)。相同的 JavaScript 值可能会产生不同的序列化输出。
【The format is backward-compatible (i.e. safe to store to disk). Equal JavaScript values may result in different serialized output.】
v8.serialize(value)#>
使用 DefaultSerializer 将 value 序列化到缓冲区中。
【Uses a DefaultSerializer to serialize value into a buffer.】
当尝试序列化需要超过 buffer.constants.MAX_LENGTH 大小缓冲区的巨大对象时,将抛出 ERR_BUFFER_TOO_LARGE。
v8.deserialize(buffer)#>
buffer<Buffer> | <TypedArray> | <DataView> 一个由serialize()返回的缓冲区。
使用默认选项的 DefaultDeserializer 从缓冲区读取 JS 值。
【Uses a DefaultDeserializer with default options to read a JS value
from a buffer.】
类:v8.Serializer#>
【Class: v8.Serializer】
new Serializer()#>
创建一个新的 Serializer 对象。
【Creates a new Serializer object.】
serializer.writeHeader()#>
写出标头,其中包括序列化格式版本。
【Writes out a header, which includes the serialization format version.】
serializer.writeValue(value)#>
value<any>
将 JavaScript 值序列化,并将序列化后的表示添加到内部缓冲区。
【Serializes a JavaScript value and adds the serialized representation to the internal buffer.】
如果 value 无法序列化,会抛出错误。
【This throws an error if value cannot be serialized.】
serializer.releaseBuffer()#>
- 返回:<Buffer>
返回存储的内部缓冲区。一旦缓冲区被释放,就不应再使用此序列化器。如果之前的写入失败,调用此方法将导致未定义行为。
【Returns the stored internal buffer. This serializer should not be used once the buffer is released. Calling this method results in undefined behavior if a previous write has failed.】
serializer.transferArrayBuffer(id, arrayBuffer)#>
id<integer> 一个32位无符号整数。arrayBuffer<ArrayBuffer> 一个ArrayBuffer实例。
将 ArrayBuffer 标记为其内容已被带外传输。在反序列化上下文中将相应的 ArrayBuffer 传递给 deserializer.transferArrayBuffer()。
【Marks an ArrayBuffer as having its contents transferred out of band.
Pass the corresponding ArrayBuffer in the deserializing context to
deserializer.transferArrayBuffer().】
serializer.writeUint32(value)#>
value<integer>
写入一个原始 32 位无符号整数。用于自定义 serializer._writeHostObject() 内部。
【Write a raw 32-bit unsigned integer.
For use inside of a custom serializer._writeHostObject().】
serializer.writeUint64(hi, lo)#>
写入一个原始的64位无符号整数,分为高32位和低32位部分。用于自定义serializer._writeHostObject()内部。
【Write a raw 64-bit unsigned integer, split into high and low 32-bit parts.
For use inside of a custom serializer._writeHostObject().】
serializer.writeDouble(value)#>
value<number>
编写一个 JS number 值。
用于自定义 serializer._writeHostObject() 内。
【Write a JS number value.
For use inside of a custom serializer._writeHostObject().】
serializer.writeRawBytes(buffer)#>
buffer<Buffer> | <TypedArray> | <DataView>
将原始字节写入序列化器的内部缓冲区。反序列化器将需要一种方法来计算缓冲区的长度。用于自定义 serializer._writeHostObject() 内部。
【Write raw bytes into the serializer's internal buffer. The deserializer
will require a way to compute the length of the buffer.
For use inside of a custom serializer._writeHostObject().】
serializer._writeHostObject(object)#>
object<Object>
此方法用于写入某种主机对象,即由原生 C++ 绑定创建的对象。如果无法序列化 object,应抛出适当的异常。
【This method is called to write some kind of host object, i.e. an object created
by native C++ bindings. If it is not possible to serialize object, a suitable
exception should be thrown.】
此方法本身并不存在于 Serializer 类中,但可以由子类提供。
【This method is not present on the Serializer class itself but can be provided
by subclasses.】
serializer._getDataCloneError(message)#>
message<string>
该方法用于生成在对象无法被克隆时将被抛出的错误对象。
【This method is called to generate error objects that will be thrown when an object can not be cloned.】
此方法默认为 Error 构造函数,并且可以在子类中重写。
【This method defaults to the Error constructor and can be overridden on
subclasses.】
serializer._getSharedArrayBufferId(sharedArrayBuffer)#>
sharedArrayBuffer<SharedArrayBuffer>
当序列化器要序列化一个 SharedArrayBuffer 对象时,将调用此方法。它必须为该对象返回一个无符号 32 位整数 ID,如果这个 SharedArrayBuffer 已经被序列化过,则使用相同的 ID。在反序列化时,这个 ID 将传递给 deserializer.transferArrayBuffer()。
【This method is called when the serializer is going to serialize a
SharedArrayBuffer object. It must return an unsigned 32-bit integer ID for
the object, using the same ID if this SharedArrayBuffer has already been
serialized. When deserializing, this ID will be passed to
deserializer.transferArrayBuffer().】
如果对象无法序列化,则应抛出异常。
【If the object cannot be serialized, an exception should be thrown.】
此方法本身并不存在于 Serializer 类中,但可以由子类提供。
【This method is not present on the Serializer class itself but can be provided
by subclasses.】
serializer._setTreatArrayBufferViewsAsHostObjects(flag)#>
flag<boolean> 默认值:false
指示是否将 TypedArray 和 DataView 对象视为宿主对象,即将它们传递给 serializer._writeHostObject()。
【Indicate whether to treat TypedArray and DataView objects as
host objects, i.e. pass them to serializer._writeHostObject().】
类:v8.Deserializer#>
【Class: v8.Deserializer】
new Deserializer(buffer)#>
buffer<Buffer> | <TypedArray> | <DataView> 由serializer.releaseBuffer()返回的缓冲区。
创建一个新的 Deserializer 对象。
【Creates a new Deserializer object.】
deserializer.readHeader()#>
读取并验证头部(包括格式版本)。例如,可能会拒绝无效或不受支持的传输格式。在这种情况下,会抛出 Error。
【Reads and validates a header (including the format version).
May, for example, reject an invalid or unsupported wire format. In that case,
an Error is thrown.】
deserializer.readValue()#>
从缓冲区反序列化 JavaScript 值并返回。
【Deserializes a JavaScript value from the buffer and returns it.】
deserializer.transferArrayBuffer(id, arrayBuffer)#>
id<integer> 一个32位无符号整数。arrayBuffer<ArrayBuffer> | <SharedArrayBuffer> 一个ArrayBuffer实例。
将 ArrayBuffer 标记为其内容已被带外传输。在序列化上下文中传递相应的 ArrayBuffer 给 serializer.transferArrayBuffer()(或者在使用 SharedArrayBuffer 的情况下返回 serializer._getSharedArrayBufferId() 的 id)。
【Marks an ArrayBuffer as having its contents transferred out of band.
Pass the corresponding ArrayBuffer in the serializing context to
serializer.transferArrayBuffer() (or return the id from
serializer._getSharedArrayBufferId() in the case of SharedArrayBuffers).】
deserializer.getWireFormatVersion()#>
- 返回:<integer>
读取底层的线格式版本。可能主要对读取旧线格式版本的遗留代码有用。可能在调用 .readHeader() 之前不能使用。
【Reads the underlying wire format version. Likely mostly to be useful to
legacy code reading old wire format versions. May not be called before
.readHeader().】
deserializer.readUint32()#>
- 返回:<integer>
读取一个原始的32位无符号整数并返回它。用于自定义deserializer._readHostObject()中。
【Read a raw 32-bit unsigned integer and return it.
For use inside of a custom deserializer._readHostObject().】
deserializer.readUint64()#>
- 返回值: 整数数组[]
读取一个原始的 64 位无符号整数,并将其作为一个包含两个 32 位无符号整数条目的数组 [hi, lo] 返回。用于自定义 deserializer._readHostObject() 内部。
【Read a raw 64-bit unsigned integer and return it as an array [hi, lo]
with two 32-bit unsigned integer entries.
For use inside of a custom deserializer._readHostObject().】
deserializer.readDouble()#>
- 返回:<number>
读取一个 JS number 值。用于自定义 deserializer._readHostObject() 内。
【Read a JS number value.
For use inside of a custom deserializer._readHostObject().】
deserializer.readRawBytes(length)#>
从反序列化器的内部缓冲区读取原始字节。length 参数必须对应传递给 serializer.writeRawBytes() 的缓冲区长度。用于自定义 deserializer._readHostObject() 内部。
【Read raw bytes from the deserializer's internal buffer. The length parameter
must correspond to the length of the buffer that was passed to
serializer.writeRawBytes().
For use inside of a custom deserializer._readHostObject().】
deserializer._readHostObject()#>
此方法用于读取某种主机对象,即由原生 C++ 绑定创建的对象。如果无法反序列化数据,应抛出适当的异常。
【This method is called to read some kind of host object, i.e. an object that is created by native C++ bindings. If it is not possible to deserialize the data, a suitable exception should be thrown.】
这个方法本身并不存在于 Deserializer 类中,但可以由子类提供。
【This method is not present on the Deserializer class itself but can be
provided by subclasses.】
类:v8.DefaultSerializer#>
【Class: v8.DefaultSerializer】
Serializer 的一个子类,用于将 TypedArray(尤其是 Buffer)和 DataView 对象序列化为宿主对象,并且只存储它们引用的底层 ArrayBuffer 的部分内容。
【A subclass of Serializer that serializes TypedArray
(in particular Buffer) and DataView objects as host objects, and only
stores the part of their underlying ArrayBuffers that they are referring to.】
类:v8.DefaultDeserializer#>
【Class: v8.DefaultDeserializer】
Deserializer 的一个子类,对应于 DefaultSerializer 所写的格式。
【A subclass of Deserializer corresponding to the format written by
DefaultSerializer.】
Promise 钩子#>
【Promise hooks】
promiseHooks 接口可用于跟踪 Promise 生命周期事件。要跟踪所有异步活动,请参见 async_hooks,它在内部使用此模块来生成 Promise 生命周期事件以及其他异步资源的事件。有关请求上下文管理,请参见 AsyncLocalStorage。
【The promiseHooks interface can be used to track promise lifecycle events.
To track all async activity, see async_hooks which internally uses this
module to produce promise lifecycle events in addition to events for other
async resources. For request context management, see AsyncLocalStorage.】
import { promiseHooks } from 'node:v8';
// There are four lifecycle events produced by promises:
// The `init` event represents the creation of a promise. This could be a
// direct creation such as with `new Promise(...)` or a continuation such
// as `then()` or `catch()`. It also happens whenever an async function is
// called or does an `await`. If a continuation promise is created, the
// `parent` will be the promise it is a continuation from.
function init(promise, parent) {
console.log('a promise was created', { promise, parent });
}
// The `settled` event happens when a promise receives a resolution or
// rejection value. This may happen synchronously such as when using
// `Promise.resolve()` on non-promise input.
function settled(promise) {
console.log('a promise resolved or rejected', { promise });
}
// The `before` event runs immediately before a `then()` or `catch()` handler
// runs or an `await` resumes execution.
function before(promise) {
console.log('a promise is about to call a then handler', { promise });
}
// The `after` event runs immediately after a `then()` handler runs or when
// an `await` begins after resuming from another.
function after(promise) {
console.log('a promise is done calling a then handler', { promise });
}
// Lifecycle hooks may be started and stopped individually
const stopWatchingInits = promiseHooks.onInit(init);
const stopWatchingSettleds = promiseHooks.onSettled(settled);
const stopWatchingBefores = promiseHooks.onBefore(before);
const stopWatchingAfters = promiseHooks.onAfter(after);
// Or they may be started and stopped in groups
const stopHookSet = promiseHooks.createHook({
init,
settled,
before,
after,
});
// To stop a hook, call the function returned at its creation.
stopWatchingInits();
stopWatchingSettleds();
stopWatchingBefores();
stopWatchingAfters();
stopHookSet();
promiseHooks.onInit(init)#>
init<Function> 在创建一个 promise 时要调用的init回调。- 返回:<Function> 调用以停止钩子。
init 钩子必须是一个普通函数。提供异步函数会抛出错误,因为这会导致无限微任务循环。
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onInit((promise, parent) => {});const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onInit((promise, parent) => {});
promiseHooks.onSettled(settled)#>
settled<Function> 当一个承诺被解决或被拒绝时调用的sett定回调。- 返回:<Function> 调用以停止钩子。
settled 钩子必须是一个普通函数。提供异步函数会抛出错误,因为它会产生无限的微任务循环。
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onSettled((promise) => {});const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onSettled((promise) => {});
promiseHooks.onBefore(before)#>
before<Function> 在承诺继续执行之前调用before回调。- 返回:<Function> 调用以停止钩子。
before 钩子必须是一个普通函数。提供异步函数会抛出错误,因为这会导致无限微任务循环。
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onBefore((promise) => {});const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onBefore((promise) => {});
promiseHooks.onAfter(after)#>
after<Function>after回调 在承诺后调用的延续执行。- 返回:<Function> 调用以停止钩子。
after 钩子必须是一个普通函数。提供异步函数会抛出错误,因为这会导致无限微任务循环。
import { promiseHooks } from 'node:v8';
const stop = promiseHooks.onAfter((promise) => {});const { promiseHooks } = require('node:v8');
const stop = promiseHooks.onAfter((promise) => {});
promiseHooks.createHook(callbacks)#>
callbacks<Object> 用于注册 钩子回调init<Function> 这个init回调。before<Function> 这个before回调。after<Function> 这个after回调。settled<Function> 这个settled回调。
- 返回:<Function> 用于禁用钩子
钩子回调必须是普通函数。提供异步函数会抛出错误,因为这会产生无限的微任务循环。
注册要为每个 promise 的不同生命周期事件调用的函数。
【Registers functions to be called for different lifetime events of each promise.】
在 Promise 的生命周期中,回调 init()/before()/after()/settled() 会在相应的事件触发时被调用。
【The callbacks init()/before()/after()/settled() are called for the
respective events during a promise's lifetime.】
所有回调都是可选的。例如,如果只需要跟踪 Promise 的创建,那么只需要传入 init 回调即可。可以传递给 callbacks 的所有函数的具体信息在 钩子回调 部分。
【All callbacks are optional. For example, if only promise creation needs to
be tracked, then only the init callback needs to be passed. The
specifics of all functions that can be passed to callbacks is in the
Hook Callbacks section.】
import { promiseHooks } from 'node:v8';
const stopAll = promiseHooks.createHook({
init(promise, parent) {},
});const { promiseHooks } = require('node:v8');
const stopAll = promiseHooks.createHook({
init(promise, parent) {},
});
钩子回调#>
【Hook callbacks】
承诺生命周期中的关键事件被划分为四个方面:承诺的创建、在调用续处理程序之前/之后或在 await 周围,以及承诺解决或拒绝时。
【Key events in the lifetime of a promise have been categorized into four areas: creation of a promise, before/after a continuation handler is called or around an await, and when the promise resolves or rejects.】
虽然这些钩子类似于 async_hooks 的钩子,但它们缺少 destroy 钩子。其他类型的异步资源通常表示套接字或文件描述符,这些资源有一个明确的“关闭”状态,用来表示 destroy 生命周期事件,而 Promise 只要代码仍然可以访问它们,就可以继续使用。垃圾回收跟踪用于使 Promise 适应 async_hooks 事件模型,然而这种跟踪代价非常高,并且它们可能根本永远不会被垃圾回收。
【While these hooks are similar to those of async_hooks they lack a
destroy hook. Other types of async resources typically represent sockets or
file descriptors which have a distinct "closed" state to express the destroy
lifecycle event while promises remain usable for as long as code can still
reach them. Garbage collection tracking is used to make promises fit into the
async_hooks event model, however this tracking is very expensive and they may
not necessarily ever even be garbage collected.】
因为 Promise 是异步资源,其生命周期通过 Promise 钩子机制进行跟踪,因此 init()、before()、after() 和 settled() 回调函数不能是异步函数,因为它们会创建更多的 Promise,从而导致无限循环。
【Because promises are asynchronous resources whose lifecycle is tracked
via the promise hooks mechanism, the init(), before(), after(), and
settled() callbacks must not be async functions as they create more
promises which would produce an infinite loop.】
虽然该 API 用于将 promise 事件传入 async_hooks,但两者之间的顺序是不确定的。这两个 API 都是多租户的,因此相对于彼此可能会产生任意顺序的事件。
【While this API is used to feed promise events into async_hooks, the
ordering between the two is undefined. Both APIs are multi-tenant
and therefore could produce events in any order relative to each other.】
init(promise, parent)#>
在构造一个 promise 时调用。这并不意味着相应的 before/after 事件会发生,只是表示存在这种可能性。如果创建了一个 promise,但从未获取过后续操作,就会发生这种情况。
【Called when a promise is constructed. This does not mean that corresponding
before/after events will occur, only that the possibility exists. This will
happen if a promise is created without ever getting a continuation.】
before(promise)#>
promise<Promise>
在 promise 的后续操作执行之前被调用。这可以是 then()、catch() 或 finally() 处理函数的形式,也可以是 await 恢复的形式。
【Called before a promise continuation executes. This can be in the form of
then(), catch(), or finally() handlers or an await resuming.】
before 回调将被调用 0 到 N 次。如果从未对该 promise 进行过任何延续,before 回调通常会被调用 0 次。在同一个 promise 被多次延续的情况下,before 回调可能会被调用多次。
【The before callback will be called 0 to N times. The before callback
will typically be called 0 times if no continuation was ever made for the
promise. The before callback may be called many times in the case where
many continuations have been made from the same promise.】
after(promise)#>
promise<Promise>
在承诺(Promise)续链执行后立即调用。这可能发生在 then()、catch() 或 finally() 处理程序之后,或者在另一个 await 之后的 await 之前。
【Called immediately after a promise continuation executes. This may be after a
then(), catch(), or finally() handler or before an await after another
await.】
settled(promise)#>
promise<Promise>
当 promise 收到解决值或拒绝值时调用。在 Promise.resolve() 或 Promise.reject() 的情况下,这可能会同步发生。
【Called when the promise receives a resolution or rejection value. This may
occur synchronously in the case of Promise.resolve() or Promise.reject().】
启动快照 API#>
【Startup Snapshot API】
v8.startupSnapshot 接口可用于为自定义启动快照添加序列化和反序列化钩子。
【The v8.startupSnapshot interface can be used to add serialization and
deserialization hooks for custom startup snapshots.】
$ node --snapshot-blob snapshot.blob --build-snapshot entry.js
# This launches a process with the snapshot
$ node --snapshot-blob snapshot.blob
在上面的示例中,entry.js 可以使用 v8.startupSnapshot 接口中的方法来指定在序列化期间如何为自定义对象保存信息,以及在快照反序列化期间如何使用这些信息来同步这些对象。例如,如果 entry.js 包含以下脚本:
【In the example above, entry.js can use methods from the v8.startupSnapshot
interface to specify how to save information for custom objects in the snapshot
during serialization and how the information can be used to synchronize these
objects during deserialization of the snapshot. For example, if the entry.js
contains the following script:】
'use strict';
const fs = require('node:fs');
const zlib = require('node:zlib');
const path = require('node:path');
const assert = require('node:assert');
const v8 = require('node:v8');
class BookShelf {
storage = new Map();
// Reading a series of files from directory and store them into storage.
constructor(directory, books) {
for (const book of books) {
this.storage.set(book, fs.readFileSync(path.join(directory, book)));
}
}
static compressAll(shelf) {
for (const [ book, content ] of shelf.storage) {
shelf.storage.set(book, zlib.gzipSync(content));
}
}
static decompressAll(shelf) {
for (const [ book, content ] of shelf.storage) {
shelf.storage.set(book, zlib.gunzipSync(content));
}
}
}
// __dirname here is where the snapshot script is placed
// during snapshot building time.
const shelf = new BookShelf(__dirname, [
'book1.en_US.txt',
'book1.es_ES.txt',
'book2.zh_CN.txt',
]);
assert(v8.startupSnapshot.isBuildingSnapshot());
// On snapshot serialization, compress the books to reduce size.
v8.startupSnapshot.addSerializeCallback(BookShelf.compressAll, shelf);
// On snapshot deserialization, decompress the books.
v8.startupSnapshot.addDeserializeCallback(BookShelf.decompressAll, shelf);
v8.startupSnapshot.setDeserializeMainFunction((shelf) => {
// process.env and process.argv are refreshed during snapshot
// deserialization.
const lang = process.env.BOOK_LANG || 'en_US';
const book = process.argv[1];
const name = `${book}.${lang}.txt`;
console.log(shelf.storage.get(name));
}, shelf);
生成的二进制文件将在启动时打印从快照反序列化的数据,使用已刷新过的启动进程的 process.env 和 process.argv:
【The resulted binary will get print the data deserialized from the snapshot
during start up, using the refreshed process.env and process.argv of
the launched process:】
$ BOOK_LANG=es_ES node --snapshot-blob snapshot.blob book1
# Prints content of book1.es_ES.txt deserialized from the snapshot.
目前,从用户空间快照反序列化的应用无法再次创建快照,因此这些 API 仅适用于未从用户空间快照反序列化的应用。
【Currently the application deserialized from a user-land snapshot cannot be snapshotted again, so these APIs are only available to applications that are not deserialized from a user-land snapshot.】
v8.startupSnapshot.addSerializeCallback(callback[, data])#>
callback<Function> 在序列化之前调用的回调函数。data<any> 可选数据,在调用callback时会传递给它。
添加一个回调函数,当 Node.js 实例即将被序列化为快照并退出时会调用它。可以用它来释放不应或无法序列化的资源,或将用户数据转换为更适合序列化的形式。
【Add a callback that will be called when the Node.js instance is about to get serialized into a snapshot and exit. This can be used to release resources that should not or cannot be serialized or to convert user data into a form more suitable for serialization.】
回调按照添加顺序运行。
【Callbacks are run in the order in which they are added.】
v8.startupSnapshot.addDeserializeCallback(callback[, data])#>
callback<Function> 快照反序列化后要调用的回调函数。data<any> 可选数据,在调用callback时会传递给它。
添加一个回调,当 Node.js 实例从快照反序列化时将会调用该回调。callback 和 data(如果提供)将会被序列化到快照中,它们可以用于重新初始化应用的状态,或者在应用从快照重新启动时重新获取应用所需的资源。
【Add a callback that will be called when the Node.js instance is deserialized
from a snapshot. The callback and the data (if provided) will be
serialized into the snapshot, they can be used to re-initialize the state
of the application or to re-acquire resources that the application needs
when the application is restarted from the snapshot.】
回调按照添加顺序运行。
【Callbacks are run in the order in which they are added.】
v8.startupSnapshot.setDeserializeMainFunction(callback[, data])#>
callback<Function> 快照反序列化后调用的入口回调。data<any> 可选数据,在调用callback时会传递给它。
这设置了 Node.js 应用在从快照反序列化时的入口点。该函数只能在构建快照的脚本中调用一次。调用后,反序列化后的应用不再需要额外的入口脚本来启动,并会直接调用回调函数及反序列化的数据(如果提供的话),否则仍需要向反序列化的应用提供入口脚本。
【This sets the entry point of the Node.js application when it is deserialized from a snapshot. This can be called only once in the snapshot building script. If called, the deserialized application no longer needs an additional entry point script to start up and will simply invoke the callback along with the deserialized data (if provided), otherwise an entry point script still needs to be provided to the deserialized application.】
v8.startupSnapshot.isBuildingSnapshot()#>
- 返回:<boolean>
如果运行 Node.js 实例来构建快照,则返回 true。
【Returns true if the Node.js instance is run to build a snapshot.】
类:v8.GCProfiler#>
【Class: v8.GCProfiler】
此 API 在当前线程中收集 GC 数据。
【This API collects GC data in current thread.】
new v8.GCProfiler()#>
创建 v8.GCProfiler 类的新实例。
【Create a new instance of the v8.GCProfiler class.】
profiler.start()#>
开始收集 GC 数据。
【Start collecting GC data.】
profiler.stop()#>
停止收集 GC 数据并返回一个对象。对象的内容如下。
【Stop collecting GC data and return an object.The content of object is as follows.】
{
"version": 1,
"startTime": 1674059033862,
"statistics": [
{
"gcType": "Scavenge",
"beforeGC": {
"heapStatistics": {
"totalHeapSize": 5005312,
"totalHeapSizeExecutable": 524288,
"totalPhysicalSize": 5226496,
"totalAvailableSize": 4341325216,
"totalGlobalHandlesSize": 8192,
"usedGlobalHandlesSize": 2112,
"usedHeapSize": 4883840,
"heapSizeLimit": 4345298944,
"mallocedMemory": 254128,
"externalMemory": 225138,
"peakMallocedMemory": 181760
},
"heapSpaceStatistics": [
{
"spaceName": "read_only_space",
"spaceSize": 0,
"spaceUsedSize": 0,
"spaceAvailableSize": 0,
"physicalSpaceSize": 0
}
]
},
"cost": 1574.14,
"afterGC": {
"heapStatistics": {
"totalHeapSize": 6053888,
"totalHeapSizeExecutable": 524288,
"totalPhysicalSize": 5500928,
"totalAvailableSize": 4341101384,
"totalGlobalHandlesSize": 8192,
"usedGlobalHandlesSize": 2112,
"usedHeapSize": 4059096,
"heapSizeLimit": 4345298944,
"mallocedMemory": 254128,
"externalMemory": 225138,
"peakMallocedMemory": 181760
},
"heapSpaceStatistics": [
{
"spaceName": "read_only_space",
"spaceSize": 0,
"spaceUsedSize": 0,
"spaceAvailableSize": 0,
"physicalSpaceSize": 0
}
]
}
}
],
"endTime": 1674059036865
}
这是一个例子。
【Here's an example.】
const { GCProfiler } = require('node:v8');
const profiler = new GCProfiler();
profiler.start();
setTimeout(() => {
console.log(profiler.stop());
}, 1000);
v8.isStringOneByteRepresentation(content)#>
V8 仅支持 Latin-1/ISO-8859-1 和 UTF16 作为字符串的底层表示。如果 content 使用 Latin-1/ISO-8859-1 作为底层表示,则此函数将返回 true;否则,返回 false。
【V8 only supports Latin-1/ISO-8859-1 and UTF16 as the underlying representation of a string.
If the content uses Latin-1/ISO-8859-1 as the underlying representation, this function will return true;
otherwise, it returns false.】
如果此方法返回 false,这并不意味着该字符串包含某些不在 Latin-1/ISO-8859-1 中的字符。有时一个 Latin-1 字符串也可以表示为 UTF16。
【If this method returns false, that does not mean that the string contains some characters not in Latin-1/ISO-8859-1.
Sometimes a Latin-1 string may also be represented as UTF16.】
const { isStringOneByteRepresentation } = require('node:v8');
const Encoding = {
latin1: 1,
utf16le: 2,
};
const buffer = Buffer.alloc(100);
function writeString(input) {
if (isStringOneByteRepresentation(input)) {
buffer.writeUint8(Encoding.latin1);
buffer.writeUint32LE(input.length, 1);
buffer.write(input, 5, 'latin1');
} else {
buffer.writeUint8(Encoding.utf16le);
buffer.writeUint32LE(input.length * 2, 1);
buffer.write(input, 5, 'utf16le');
}
}
writeString('hello');
writeString('你好');