Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

node:v8

Jco provides the Node 24.20.0 node:v8 export surface. Native operations use an explicit jco:node/v8@0.1.0 capability and are denied by default.

Enable the Node provider

Application source keeps ordinary Node imports:

import { serialize, deserialize, getHeapStatistics } from 'node:v8';

const bytes = serialize({ message: 'hello', count: 42n });
console.log(deserialize(bytes));
console.log(getHeapStatistics());

Bundle with Jco’s Node builtin support, then explicitly grant the host capability:

jco componentize app.js --bundle --wit app.wit -o app.wasm
jco transpile app.wasm -o out \
  --map 'jco:node/v8@0.1.0=@bytecodealliance/jco-std/wasi/0.2.x/node/24.x.x/v8/host/node'

Importing the module does not access the provider. Without an explicit mapping, native operations throw ERR_JCO_V8_ADAPTER_REQUIRED. The portable adapter can also be imported directly from jco-std alongside ordinary Node builtins.

Host diagnostics and controls

The provider delegates these operations to public node:v8 APIs:

  • cachedDataVersionTag, heap, heap-space, code and C++ heap statistics;
  • getHeapSnapshot, writeHeapSnapshot, and setHeapSnapshotNearHeapLimit;
  • GCProfiler and startCpuProfile;
  • setFlagsFromString, takeCoverage, and stopCoverage.

These operations inspect or affect the Node host V8 isolate. They do not inspect the QuickJS or SpiderMonkey guest heap. Snapshot paths, coverage settings, and V8 flags belong to the host process. The cached-data tag describes host V8; it cannot establish compatibility with guest compiled code.

getHeapSnapshot returns a portable byte-mode Readable. The provider gathers the synchronous native snapshot before copying it into the component, so this requires additional memory and does not provide incremental host streaming. Profiles stop and release their native resource on stop() or disposal. Repeated stops return undefined, matching the pinned runtime.

startCpuProfile requires a Node host that provides that API. On older hosts, including Node 22, it throws ERR_JCO_UNSUPPORTED_NODE_API. Other V8 operations remain available when supported by the host.

Serialization

serialize and deserialize use the native V8 binary format. Serializer, Deserializer, DefaultSerializer, and DefaultDeserializer support headers, values, unsigned integers, doubles, raw bytes and wire-format inspection. Successive value writes and reads preserve object identity through the native serializer.

The shared component transport supports primitives, bigint, special numbers, cyclic plain records and arrays, Map, Set, Date, RegExp, ArrayBuffer, DataView, and the integer/float typed arrays available in both engines. The default serializer also preserves Buffer branding and visible bytes.

The transport rejects accessors, custom prototypes, Error objects, Float16Array, shared memory and native objects with explicit errors. Functions and symbols cannot be serialized. Serializer subclasses, custom native serialization hooks, and transferArrayBuffer registrations are unsupported across the component boundary. The corresponding entry points throw ERR_JCO_UNSUPPORTED_NODE_API. No JSON substitute is returned as a V8 serialization buffer.

Buffers cross WIT by value: readRawBytes returns a copy rather than a view into the caller’s original input. Deserialization takes a snapshot of the input bytes at construction. Changes to the input afterwards are not visible to the native reader. Native format versions are controlled by the selected host Node release.

releaseBuffer() releases a writer’s native resource; a subsequent write reopens it. Serializer and deserializer objects additionally expose Symbol.dispose for deterministic cleanup of abandoned writers and completed readers. The convenience functions clean up their resources automatically.

Guest engine restrictions

promiseHooks, queryObjects, and isStringOneByteRepresentation throw ERR_JCO_UNSUPPORTED_NODE_API: guest promises, constructors and string storage cannot be inspected through a host V8 call.

startupSnapshot.isBuildingSnapshot() returns false. The three startup callback registration methods throw ERR_NOT_BUILDING_SNAPSHOT, matching ordinary Node execution outside its snapshot builder. Componentization does not run Node’s startup-snapshot callbacks.

Implementation

The compatibility target is Node v24.20.0, source commit 71b8b174857e25106d39b61a9e6f30d927da8b01. Public declarations are reconciled with @types/node 24.13.3 and do not require consumer Node types.

Native V8 owns binary serialization and diagnostics. Jco reuses its shared errors, validation, Buffer, Readable, and the graph transport extracted from the worker-threads implementation. Workers retain their existing cloning policy; V8 opts into Buffer preservation and persistent reference sessions.

The unenv V8 module uses mock statistics and inert serializers, so it is not used. The codec audit also considered @ungap/structured-clone, devalue, flatted and the existing cluster JSON transport. The shared worker codec already preserves the required backing-buffer relationships and clone-marking policy; V8 adds session identity without replacing the worker format.