Skip to content

Releases: volter-ai/tabnode

v0.15.1

Choose a tag to compare

@github-actions github-actions released this 14 Oct 16:44
  • An awaiting turn queues one microtask, not two (browser-substrate S2 AC-LC9). A compiled async function's
    resumption made a closure and queued it to end its turn's account, and queued a second task to put its context
    frame back to the root where its frame changed; the turn's end is now one function, queued once, and it puts the
    frame back too. Where a turn's end was already pending, the frame now goes back with it, before a task queued in that
    turn rather than after it, as the next turn's start from the root has it.

v0.15.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 14:19

Kept paths carried across runs (browser-substrate ADR-0152, S2 AC-LC10). Additive: two new exports, which a host
detects by their presence before it hands a seed, so an engine without them is never asked; nothing a realm resolves
changes for a host that hands none, and no lowered text changes, so the prepared format stays tabnode-prepared-7.
Cut as 0.15.0, a minor release, for the new public exports.

  • A process can start with the paths its project's last run kept (browser-substrate ADR-0152, S2 AC-LC10).
    seedKeptResolutions(entries, filesystem?) seeds every kept-paths table the realm makes (only that filesystem's, where one is named) with (directory + "\0" + name, path)
    pairs, within R76's bounds; keptResolutions() returns what the realm's tables keep now. The host hands a seed only
    for a table resolved on the same files; nothing changes for a host that hands none. resolveSplit.keptPaths.carried
    says how many a table started with.

v0.14.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 11:55
  • Breaking: tabnode's scope form leaves the public API (browser-substrate ADR-0129 step 3). A container owner no
    longer hands a run from its realm's registry to another realm's: createProcessRegistryScope,
    ownerProcessRegistryScope, ownerProcessTable and ProcessRegistryScope.adoptRun are removed. A host gives each
    realm a kernel's registry through installProcessRegistry, which stays, as does the engine's own local registry
    for a realm no host gives one. Released as 0.14.0: in 0.x a minor version carries a breaking change, so a ^0.13
    consumer is not moved onto it.

v0.13.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 10:49

The browser-substrate ADR-0129 integration (the kernel owns every process), with the synchronous-child ownership
below. Each feature is additive and announced by a marker a host checks before it relies on it, so an engine without
it is never asked; none changes the lowered text, so the prepared format stays tabnode-prepared-7. Cut as 0.13.0, a
minor release, for the new public run options and exports.

  • The engine as a client of the kernel's store, its citations naming ADR-0006 on this line.
  • A run's fd 0 can be a reader over the host kernel's own pipe (RunOptions.stdinReader; marker RUN_STDIN_READER).
  • A process's signal listeners are its dispositions, told to its registry (ProcessRegistry.disposition; marker
    RUN_SIGNAL_DISPOSITIONS); a listener's name reaches the disposition words only as a signal's own name.
  • Behaviour change for a host whose registry sets ProcessRegistry.kernel: a host-run child's kill() now goes
    through the kernel registry (the kernel delivers it), where 0.12.0 ended the run itself. A kernel refusal (EPERM)
    is thrown out of ChildProcess.kill(), and SIGSTOP and SIGCONT are delivered as SIGTERM (no stop is modelled
    yet). A host that does not set kernel is unchanged.
  • A run handed its own tree gets that tree's shell at routing, and run() reads RunOptions.filesystem as runNode
    does (marker RUN_LINE_FILESYSTEM); tokenOfPid takes the caller's pid namespace.
  • A run's initial environment is published with its identity, for the process table's /proc/<pid>/environ.
  • A TCP server or Unix-socket listener passed over IPC is a duplicate of its socket, as SCM_RIGHTS duplicates a
    descriptor: before, it crossed as the sender's own instance, so the sender's close ended the receiver's listener.
    Either member accepts, in turn, and the socket listens until its last member closes; a bound, not-yet-listening
    socket (cluster's shared handle) keeps its bound name in the copy. A connection reaching a socket no member serves
    yet waits in the socket's accept queue, owned by no run until a member accepts it; the last listener's close
    resets what is queued (ECONNRESET), as Linux does. For a Pipe, the binder's close takes the socket's path with its
    node, as libuv and Linux do, and a passed copy accepts only by descriptor; a socket in the abstract namespace has
    no node, so its name passes at a close to a member still open.
  • Let a trusted synchronous child host explicitly own all children of the current
    run, including image scripts and Node programs the engine can resolve. Use the
    existing admitted host process/wait path before Worker fallback; preserve
    other embeddings' classification, precise refusals and raw Worker restriction.
    Honor explicit host image-handoff/end evidence before synthesizing a local
    launch failure; an admitted child still reaps its actual kernel end.
    The paired page retires its original descriptor release lease separately
    from an image's own close/end, including when Node receives a second channel.
    Source only; paired host integration, release and application qualification
    remain separate (substrate Articles 1/5/6/8/9).

v0.12.0

Choose a tag to compare

@github-actions github-actions released this 14 Oct 06:15
  • A rewritten new passes the making module's dynamic import in both of the engine's lowerings (Codex 91): the
    guest-name rewrite passed only $process, so a guest-scoped body's new Function(...) lost its module's loader,
    while the with-scope rewrite passed it. The lowered text changes, so the prepared format moves to
    tabnode-prepared-7: bodies prepared by 0.11.x (format 6, the old constructor wrap) are not found and are prepared
    again, at both scoped runModuleBody read paths. A minor release, 0.12.0 (CONTRIBUTING's rule; the merge that sets
    the version is published as it, RELEASING.md). String(fn) restores both wraps, which only gives back source text
    and never upgrades a stale body's execution.

v0.11.2

Choose a tag to compare

@github-actions github-actions released this 14 Oct 04:17
  • The publish workflow sees a version set in a merge commit: .github/autorelease.mjs reads the version line's last
    change with --first-parent, so a merge to main that sets a minor version is published as that version. Before,
    git log -G skipped merges and took the bot's last release commit as the setter, so the merge of w3/load-clock
    that set 0.11.0 was published as 0.11.1.

v0.11.1

Choose a tag to compare

@github-actions github-actions released this 14 Oct 04:10
  • Merging w3/load-clock into main: both lines had moved the prepared format to tabnode-prepared-5 for
    different lowerings (main's for #12's made-function loader, load-clock's for K1/R16's guest-scope rewrite), so a
    body prepared by v0.10.x would be taken under the same name by an engine that lowers its source differently. The
    merged engine has both changes and moves the format to tabnode-prepared-6; bodies prepared by any earlier
    version are prepared again (CONTRIBUTING's rule, a minor release).
  • Throw Node's ERR_PACKAGE_PATH_NOT_EXPORTED from require when the first package found has an exports map that names the subpath under no condition set, and stop the walk there; before, the resolver returned null, the walk went on to parent and global roots, and require said MODULE_NOT_FOUND. A program that branches on the code read the wrong answer: MeshCentral 1.2.6 took require("otplib/package.json") for a missing module and went to install it with npm. Stand-ins still answer first. A map that names the subpath but points at a missing file is unchanged, and so is the bundler's resolver (substrate Articles 5/8/9). require.resolve(id, { paths }) lets that refusal end its lookup instead of trying the next directory, and a package's self-reference to a subpath its map refuses is refused the same way (Node's packageSelfResolve).
  • Preserve explicit receiver resource ownership during adoption, ignore Process reference changes before initialization, and permit watcher reference changes until pending close completes (substrate Articles 5/6/8/9).
  • Keep transferred stream requests with their adopted handle owner, retain directory operation scopes, and share process.binding’s native surface with the process-owned internal binding cache (substrate Articles 5/6/8/9).
  • Preserve failed watcher-start and exact Process close-callback observations; give explicit binding ownership priority over ambient guest tokens in nested standalone runtimes (substrate Articles 5/6/8/9).
  • Correct standalone accepted-handle custody, failed-spawn initialization and polling-watcher initialization/close observations in process enumeration; preserve real resource identity and existing liveness/transport behavior (substrate Articles 5/6/8/9).
  • Add process._getActiveHandles and process._getActiveRequests over real process-owned binding wrappers and requests, following Node’s owner links and reference filtering. Preserve resource identity, liveness accounting and transport behavior; remove observations on completion, close and exit. Activepieces’ pm2 caller previously threw because these APIs were absent (substrate Articles 5/6/8/9; source reading). Source only; application qualification remains open.
  • A run's native-binding map (the substrate's ADR-0094) is given to the engine as data, once, and applied inside
    its own resolution only where it can apply, so no require runs a resolve hook (S2: the hook chain was ~83 ms of
    LibreChat's server start in the tab). The map is fixed once given (a non-writable property, a frozen lookup), and a
    file: specifier is read by Node's own fileURLToPath, so an encoded '/' or a foreign host still throws. One answer
    changed: requirePlain's rollup, esbuild and prettier intercepts run before the map, so a request for one of them
    that the map would have refused (or that does not resolve) is answered with the engine's stand-in, where the hook
    answered MODULE_NOT_FOUND or ERR_UNPREPARED_PROVISION. That is the engine's own answer with no hook, and it is
    kept (Articles 5/9).
  • Route native-addon fcntl/flock and logical POSIX close through the captured
    process/tree's actual descriptor owner, refusing absent authority and
    foreign descriptors; preserve Node's library files and ordinary fs APIs
    (Articles 5/6/9). Source only, paired runtime review/admission remains.
  • Requested module evaluation evidence includes the digest of original _compile text, or the verified source digest selecting an image-prepared body, and whether the completed synchronous body replaced exports. Only an explicitly selected source is hashed; original loading, cached-body use, exports and errors remain unchanged. Host callbacks receive immutable scalar evidence, and source records retire when their compilation or prepared-body execution ends (substrate Articles 1/5/6/8/9).
  • Failed child host handoff (substrate Articles5/6/8/9): a synchronous throw or
    rejected host run returns exit ownership only when the holder confirms no image
    started and no end was posted. Publish a launch failure as127 (126 for permission
    denial); live images, unknown lifecycle and already posted ends keep their host
    exit ownership and descriptor-close ordering. Print a bounded code, child pid
    and command path in the console without writing to a parent's protocol stderr.
    Full production declarations emit against load-clock1e4e9e6; independent review
    and the paired substrate cleanup's application reading remain pending.
  • K1/R16 evaluate (substrate Articles5/6/9; lead ruling m-71c68f37): a module
    body runs in Node's own wrapper form, with no with. Preparation rewrites only
    the free references to the 19 guest-global names (reads, writes, typeof,
    updates, shorthand properties) to __substrateGuestScope.<name>, a bare call
    keeping Node's undefined receiver; every other free name resolves lexically,
    then globally, as in Node, instead of as a dynamic lookup through the with
    object at every call. A body with a with statement or a direct eval, or one
    that does not parse, keeps the with wrapper. Prepared bodies move to format
    tabnode-prepared-5 (-6 once merged with #12's; see above). Unchanged from before: a bare read of a guest name the
    guest lacks gives undefined where Node throws. A function's text
    (Function.prototype.toString) reads as written: each edit's shape names the
    reserved scope and is told apart by its own text, a body that names the
    reserved names or writes a guest name with escapes keeps the with wrapper,
    and a new callee's constructor wrap is undone too. Scopes follow Node's
    (function and catch parameters do not see body declarations, a block's class
    or a strict block's function is not hoisted, a static block is its own var
    scope); a source's own guest-scoped mark is blanked, never trusted. Source only.
  • PLACEMENT-LOADER current-head integration (substrate Articles1/2/5/6/8/9):
    merge approved private observation with34b5101's counted bodies, forwarding
    utf8Bytes unchanged, and enable only an own observer options property via a
    captured native check without absent-case allocations. Original worker/index
    bundle stages and all declarations emit; receipt.
    Actual inspector/vendor-loader transport remains independently unqualified.
  • PLACEMENT-LOADER-RECORDS (substrate Articles1/2/5/6/8/9): replace filename
    arrays with the host's private observes predicate over frozen records.
    Own module state uses captured reflection and frozen argument records with
    no prototype, excluding inherited array setters and mutable selection.
    Changed worker/library bundles, runtime module closure and all declarations
    emit within the original fixed bound; build receipt.
    Real paused-inspector/loader transport and manifest identity remain unqualified.
  • PLACEMENT-LOADER-INTRINSICS (substrate Articles1/2/5/6/8/9): capture
    requested observer Reflect/Object/Set intrinsics before guest entry,
    populate selection with indexed access, and observe only own loaded/export
    data descriptors. Guest replacement of shared-realm methods cannot forge
    the selection or its observer callback. Changed index/worker output and
    all declarations emit in separate bounded stages of the unchanged config;
    build receipt.
    Private consumer output and actual app/inspector transport await review.
  • PLACEMENT-LOADER-HOST (substrate Articles1/2/5/6/8/9): allow a local
    execution host to observe successful synchronous module evaluation at
    exact selected filenames through private Runtime/RunOptions. Ordinary
    execution installs no body wrapper or per-body check. No guest global,
    public Module hook, child-host inheritance or vendor call is added;
    original outcomes remain intact. All original library outputs and declarations
    emit in bounded, separate production invocations of the unchanged Vite
    config; source/build receipt.
    Actual application observation and consumer transport remain unqualified.
  • R5 reading: the load clock says its body-count input's declared retained
    bytes, now and at their peak (retainedInputBytes, peakRetainedInputBytes),
    beside the exact-or-null byte totals. Readings only.
  • R5 counted bodies (substrate Articles5/6/9): where a reading is requested and
    the tree says a prepared body's exact UTF-8 length beside its text (the
    substrate's readTextCounted), the body is counted at once and only 64 bytes
    are retained for it, not its text. A tree that says no length leaves the
    body to the deferred count, unchanged. Source only.
  • R5 retention (Articles5/6/8/9): declare deferred load-clock prefix inputs
    to the host's share of the requested 256 MiB tab trace bound; drop/release whole source cohorts
    with explicit loss and null subsequent byte totals. Exact surviving UTF8
    cohorts still materialize only after release or before terminal handoff.
    Terminal ownership releases arrays while retaining cumulative scalars.
    Old-host delivery remains compatible; no raw-file-length shortcut lands.
  • S2 K1 compile (substrate Articles5/6/8/9): a body's wrapper no longer carries
    the 19 guest-global accessors as an object literal. One null-prototype scope
    of the same live, sloppy-silent acce...
Read more

v0.10.1

Choose a tag to compare

@github-actions github-actions released this 13 Oct 19:30
  • Merge pull request #11 from volter-ai/w3/a-served-request-carries-its-referer
  • The Referer is given only to the server the asking page was itself served by
  • A request a page makes to its own server carries the Referer a browser would send it

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 13 Oct 19:19
  • import() inside a function made with new Function loads through the module that made the function, so its
    specifiers resolve as that module's own would (#12). The lowered module text changed with it, so
    PREPARED_MODULES_FORMAT is now tabnode-prepared-5, and modules prepared by an earlier version are prepared
    again: a minor release under CONTRIBUTING's rule (#13).

v0.9.1

Choose a tag to compare

@github-actions github-actions released this 13 Oct 19:14
  • To follow, not yet changed: four optional members added in v0.9.0 and before
    are second paths that only an embedder without them takes (the stream
    transport's post, a started run's setRef, the host request's
    hold.changed, the tree's contentDigest). Once browser-substrate
    implements all four they become required, and the paths without them go.