Shared TypeScript and runtime guards for retained resources passed between
modular Vinary Tree packages. The package does not create a second resource
table: resources are created by the selected @vinary-tree/javascript-runtime
native, WASM, or WASI runtime and carry that runtime's identity.
Project facades use assertSameRuntime before accepting a resource and use
assertDictionaryResource to require vt.dictionary.v1. Concrete dictionary
constructors and CRUD remain in @vinary-tree/libdictenstein.
Applications can also define immutable lattice values, dynamic semirings, and scalar weighted finite-state transducers (WFSTs) directly in JavaScript or TypeScript. The package exports structural TypeScript interfaces, fail-closed runtime guards, and canonical option normalizers for all three contracts. The complete method, paging, lifetime, failure, and backend contract is the JavaScript host-provider guide.
Scalar-WFST, lattice, and dynamic-semiring providers are executable through the native Node-API, browser WebAssembly, and Node WASI backends. The semiring guards are the runtime-neutral contract boundary used by all three backend trampoline implementations.
| Property | Contract |
|---|---|
| Binding | JavaScript family |
| Languages/runtime | JavaScript, TypeScript, and ClojureScript on Node.js, browsers, or WASI |
| Support tier | Tier 1 |
| Distribution | npm package @vinary-tree/vinary-tree-interop |
| Native boundary | This adapter represents the two-word VtResource capability and its versioned interfaces; it does not implement a dictionary or automaton. |
| Canonical facade source | vinary-tree-interop/bindings/javascript |
The support tier controls release gating, not semantic quality: every tier has the same snapshot, ownership, status, and ABI compatibility laws. Consult the binding architecture before implementing a custom provider and the family hub when combining independently packaged projects.
test.mjs exercises the same ESM exports and resource-identity
checks that users install. The package also exposes equivalent CommonJS and
TypeScript declaration entrypoints. Run its gate from the repository root with:
npm test --prefix bindings/javascriptProject-specific constructors live in their own packages; this neutral package only models and validates the shared resource handoff.
The idiomatic facade groups the stable surface into these concepts:
| Concept | Semantics |
|---|---|
VtResource |
Two pointer-sized words: an opaque context and a base vtable. A borrowed value transfers no ownership. |
| Base vtable | struct_size, ABI version, retain, release, and query_interface; it is the only mandatory interface. |
| Dictionary interface | Snapshot capture, node paging, finality, optional values, unit/value domains, and capability flags. |
| Dictionary entries interface | Optional finite lexicographic stream over one captured revision, with bounded arena batches, exact generation leases, cancellation, and a reducer path. |
| Scalar-WFST interface | Snapshot capture, start state, final weights, paged arcs, label/weight domains, and capability flags. |
| Lattice interface | Immutable join, meet, equality, diagnostics, optional canonical bytes, and optional bounded folds. |
| Dynamic-semiring interfaces | Identities, algebra, comparison, optional canonical bytes and batches, optional division, closure, numerical projections, and declared laws. |
Unit and value domains are explicit enum fields on the discovered interface; adapters must never infer them from host container types. Empty terms, embedded zero bytes, non-ASCII text, and the full unsigned 64-bit identifier range are represented explicitly; no facade may use a sentinel value that removes a valid input from the domain.
For the exhaustive native function contract—including exact preconditions, returnable statuses, complexity, and thread-safety—use the family resource ABI reference. The facade source linked above is the authoritative idiomatic symbol inventory; its exhaustive coverage is pinned by the canonical C header and the Rust layout and discriminant tests.
Use explicit resource management (using) where available or call close()/close! in finally. GC finalizers are fallback containment. Close every entries cursor, and release its current generation before advancing or closing it.
A borrowed resource becomes owned only after a successful retain. Interface
discovery does not transfer ownership, and a failed validation must release any
retain already acquired. A captured snapshot owns an independent revision and
may outlive the producing project handle. Release exactly once for every
successful retain; never release an unretained borrowed pair. An entries cursor is move-only and owns its
captured revision until close. Exactly one generation may be live: release
that exact generation before advancing, reducing, or closing; reducer batch
views expire when their callback returns.
Borrowed results are intentionally lexical. Copy data that must outlive the callback; retaining a raw address, slice, memory segment, or foreign pointer is an API violation even when the next operation happens to reuse the same arena.
Interop validation failures preserve VtStatus; project facades map that status into their own public error currency.
Null resource words, truncated vtables, incompatible interface identities or versions, invalid domains, forged node/state identifiers, malformed page counts or entry arenas, stale or mismatched batch generations, live-batch conflicts, provider faults, and contained panics are distinct failures. Never parse diagnostic prose to branch on an error: inspect the typed status/exception first and treat the message as human context. Diagnostics must be copied before another native call on the same thread.
A retained resource may cross threads only when its advertised interface flags permit it. Retain and release remain balanced under every failure path. One entries cursor and its live batch are single-consumer; reducer callbacks must not reenter that cursor.
Snapshot capture is a linearization point, not a dictionary-wide query lock. First-party immutable snapshots can be walked concurrently. A foreign provider that does not advertise parallel callbacks is serialized at its callback gate; the host language must not add a weaker promise.
- Pass the two-word resource by value; do not serialize or copy the graph.
- Capture one immutable snapshot and page nodes/arcs through bounded buffers.
- Negotiate entries-v1 when exact lexicographic enumeration is needed; honor all entry/unit/value limits on every batch.
- Cache a validated optional interface only while the owning resource remains retained.
- Respect capability flags before enabling parallel callback entry.
- Prefer a compact immutable graph interface when advertised; retain the paged callback fallback for compatibility.
Treat a foreign resource provider and all user-controlled queries as untrusted inputs. Validate lengths before allocation, preserve paging bounds, reject unknown enum values, contain callbacks/panics at the boundary, and never trust capability flags until interface negotiation succeeds. The normative duties are in the binding trust model.
The project ABI revision, family ABI version, interface identity/version, package version, and umbrella-runtime version are independent counters. Follow the ABI evolution policy; never infer compatibility from a package version alone.
When loading fails, check—in order—the documented runtime/toolchain version, CPU/OS artifact, native-access permission, loader search path, dependent interop package pin, and process-wide JavaScript runtime identity. When a query fails after construction, report the typed status and copied diagnostic before reducing the case to the smallest dictionary/query pair.
- Update the interop generator model before changing a layout, identifier, flag, or enum.
- Regenerate headers/constants and the API coverage matrix.
- Extend the canonical executable example and negative-path tests.
- Run the language package, snapshot, leak, property, and cross-project suites.
- Verify package staging contains this guide and uses coherent sibling pins.
- Render diagrams headlessly and run the documentation/link/math gates.