@volter/browser-node
v0.1.93
Published
Tabnode, Node, npm, and Vite execution lane for the Volter browser runtime
Readme
@volter/browser-node
The Node execution engine for Browser Substrate. It adapts Tabnode to the
engine-neutral process, filesystem, port, WebSocket, and streaming contracts in
@volter/browser-runtime, and adds npm and Vite support: npm runs a project's
scripts and links its prepared packages, and every install it is asked for is
refused before it starts (@volter/browser-runtime/install-trap.js).
Import createBrowserNodeRuntime to construct a runtime with this engine. Use
@volter/browser-node/vite in the host application's Vite configuration to
emit the cross-origin-isolation and sandbox assets the browser needs.
prepareBrowserNodeProgram(filesystem, manifest, options) materializes a Node
program's pinned bundle and resources without executing it. Await it before
starting a deadline that measures program execution, such as waiting for a
server port. It accepts the same artifact URL, integrity and progress options
as BrowserNodeProgram; subsequent runs reuse the prepared archives through
the existing installer.
With bundlerWorkerPath configured, that Vite plugin also emits the optional
Rolldown browser assets. Set node.rolldownModuleUrl to
"/rolldown/factory.mjs" to enable lazy loading for an installed Rolldown
1.2.7 package. Its main, experimental, utilities, plugins, filter, and parser
exports use a binding owned by the runtime's filesystem. Other package
versions retain their installed loader. The binding has a 512 MiB memory
ceiling and an eight-worker limit; disposing the runtime releases it.
npm run verify:rolldown in the repository exercises two instances in normal
Chrome, concurrent plugin resolution, output writes, parser access, edits,
and independent worker disposal.
Framework admission is tracked separately in the repository roadmap.
Guest node:crypto supports real MD5 and SHA-1/224/256/384/512 through createHash,
createHmac, one-shot hash, and synchronous/callback pbkdf2. Hashes consume
input incrementally, support copy(), and return guest Buffers or encoded text,
including base64url. PBKDF2 requires positive integer iterations and output length;
its callback is deferred, but the derivation runs in the guest's JavaScript realm,
not an additional worker pool. getHashes() lists the supported digests.
These adapters cover update/digest; Node's hash/HMAC stream API is not supplied.
Unsupported algorithms (including SHA-3) and synchronous signing or
verification fail explicitly. Failed asynchronous WebCrypto signing/verification
propagates its error without a fabricated fallback. npm run verify:crypto
exercises the browser paths with an unchanged dependent package and reload recovery.
Guest util.styleText supplies basic style wrapping and non-terminal suppression.
It preserves embedded reset codes; reopening styles after those resets is not
implemented. Its output does not vary with the host Node version used to build it.
The execution-worker lane supports up to eight guest worker_threads per runtime
with file entries, cloned workerData/environment, cwd, shared filesystem access,
ArrayBuffer transfer, SharedArrayBuffer messages, output, ref/unref and
termination. Parent cancellation/disposal releases children. Thread networking,
nested workers, message-port transfer, environment-data APIs and custom resource
limits are unsupported and fail explicitly. Filesystem channel writes are bounded
by its buffer (4 MiB by default); watches and POSIX link/metadata operations are
not implemented for threads. This is not full Node worker compatibility or a heap
quota. Other runtime lanes refuse Worker construction. verify:node-threads
exercises this boundary in normal Chrome.
createIsolatedBrowserNodeRuntime({ shared }) creates another cross-origin
worker that reuses a parent-owned filesystem and virtual ports bridge.
This is the service-pool primitive used by native in-tab Compose: each service
gets a hard worker boundary without copying the workspace or inventing a
second network.
This package owns all Tabnode-specific behavior. The runtime kernel does not depend on it.
createConfinedNodeFilesystem from confined-virtual-filesystem.js constructs an
invocation-owned filesystem view over a Tabnode VirtualFS, using the runtime's
writableRoots policy. Reads remain broad and byte buffers are copied; writes,
rename endpoints, metadata and descriptor opens/writeback enforce the grant.
Unsupported links refuse. The worker-backed Node lane negotiates confined execution:
each command gets its own engine/bundler worker and an immutable filesystem
channel enforced by the workspace owner. Runtime loader files remain private;
children inherit the grant and the receiving host intersects it again. Older
workers without the version-1 handshake refuse before executing. Cancellation
ends the command worker and its children, closes its watches and ports, and
rejects outstanding HTTP requests. Confined HTTP and Vite servers register in
the shared port table, refusing collisions, and receive holder filesystem
changes for watches and HMR. Writes retain the same grant while serving.
The root supervisor may load at most two unassigned execution workers ahead of admission, inside its existing sixteen-worker ceiling (ADR-0060). Loading the engine grants no filesystem or process authority. Admission supplies those grants through the same handshake; a used worker is terminated, and runtime disposal also terminates any unused workers.
Confined commands can connect to TCP listeners registered with listenNet().
Listener changes reach running commands; each command owns at most 128 bridged
sockets, with capacity released on close and endpoints closed on cancellation.
Connection ids remain separate across concurrent confined and ordinary clients.
Filesystem restrictions also apply inside socket callbacks.
The page-thread lane still refuses confinement. Bundler factories that require direct global Worker construction refuse; the configured esbuild host retains its own worker constructor and guarded filesystem channel. Confined workers and channel-backed Node threads cannot directly open origin storage or create arbitrary workers. These limits do not change unconfined command routing.
