Skip to content

Back to Releases

ivue@2.3.0 ​

View on GitHub ↗Released August 23, 2026

Feature release — one new export, zero breaking changes, and the core engine untouched: ivue/extras gains LazyShared, the cell that closes the last open seam in the class-module system. The primary ivue entry stays the bare 1.1 kB engine.

LazyShared — the safe shared-store cell ​

A shared static store has to hold two properties at once, and until now JavaScript made you pick one:

  • Load-lazy — a static readonly field initializer runs at module load, so constructing another module's class there races the import cycle. $-cached static getters defer correctly — but they cache per receiver, so a subclass reads a fresh, empty copy.
  • Unforkable — one value per process, every access path — base class, subclass, $-cache — converging on the same object.

LazyShared is both. The field eagerly stores the cell; the cell holds an inert thunk; the value constructs on first read — after every import cycle has resolved — and memoizes inside the cell, never on a receiver, so there is nothing forkable at the end of any access path:

ts
import { LazyShared } from 'ivue/extras';

class $SearchRegistry {
  protected static readonly sharedBackend = new LazyShared(
    () => new SearchBackend.Class(),
  );

  protected static get $backend() {
    return this.sharedBackend.value;
  }
}

The surface is three members — new LazyShared(make), .value, .reset() (the test seam) — and two failure modes are engineered rather than left to chance: a thunk cycle throws a named error that tells you which dependency to break, and a throwing thunk never poisons the cell (the next read retries).

With it, the combined Reactive() + Static() system is memoizable at every scope — instance, receiver, shared — with polymorphism, inheritance, and performance intact. The full map, every value kind in working code: Bulletproof class modules.

The Standard, grown again ​

npx ivue skill ships the current Standard Operating Manual (845 → 1,033 lines), with the conventions that landed alongside the new cell:

  • self — the one cast per class. Instance code reads its own statics through protected get self() { return this.constructor as typeof $X } — late-bound, so subclass overrides are honored, and declared once beside the statics it types instead of asserted at every call site. Measured: ~2 ns per read over an inline cast; the hoisted const self = this.self form in loops measures faster than inline casts (~0.4 ns vs ~4 ns per iteration, Node 26, production build).
  • The shared-store split as two questions. Does a subclass get its own copy (memo → $-getter) or not (registry → static readonly field pin)? And does construction cross a module boundary (→ the field holds a LazyShared cell)?
  • Restructured for coherence: the manual now reads as three parts — the Reactive() instance world, the static world from ivue/extras, and the style contract.

Docs ​

Numbers ​

  • Core ivue entry: byte-identical to 2.2.2 — 1.1 kB gzipped, zero dependencies.
  • ivue/extras grows by the ~40-line cell; engine and extras test coverage stays 100%.

Released under the MIT License.