Skip to content

v0.19.1

Choose a tag to compare

@PatrickJS PatrickJS released this 31 Jul 23:08
· 4 commits to main since this release

Release notes from CHANGELOG.md for @async/framework@0.19.1 (2026-07-31).

  • Fixed pre-runtime app.applySnapshot(...): snapshots without a flow key
    no longer throw, and snapshot browser-cache entries now reach the first
    runtime instead of being dropped.
  • Unified the reveal vocabulary in src/reveal-policy.js, shared by the
    boundary receiver and the build optimizer. The receiver now accepts the
    optimizer's default tail visible (normalized to "no tail treatment")
    instead of throwing.
  • AsyncStream patches resolved through a runtime or loader now share one
    receiver per loader, so sequence dedup and reveal buffering work across
    inline stream scripts.
  • Errored patches carrying reveal metadata settle their reveal index so
    ordered and together groups commit buffered siblings instead of stalling
    forever.
  • applyServerResult no longer blanks a boundary for envelopes with
    html: undefined or status: 204, matching the router's swap accounting;
    the router now shares the exported isServerEnvelope predicate instead of
    a drifted truthy wire-key check.
  • Bare * route segments compile as anonymous rest splats (previously scored
    as wildcards but compiled as the literal character *).
  • signal:class:x now delegates to the shared class-token writer, removing a
    binding-key collision with class:x that silently dropped one of the two
    bindings.
  • Expired server-route prefetch entries are swept on insert instead of
    accumulating for the router's lifetime.
  • Removed dead code that duplicated live implementations: parsePath in
    signals.js, isAsyncSignalSnapshot in app.js, and a no-op template branch
    in the loader's swap HTML renderer.
  • Centralized the typed-registry CRUD scaffolding
    (createTypedRegistryMethods in registry-store.js): the handler, partial,
    component, cache, and server registries now share one
    register/registerMany/unregister/_adoptMany implementation instead of five
    drifting copies. Route and signal registries stay custom by design.
  • Replaced the three hand-rolled pending facades in app.js (loader, router,
    router-loader) with one createPendingFacade implementation; per-facade
    differences (commit-await methods, _clearCurrent batch clearing) are now
    explicit options.
  • Extracted shared DOM helpers into src/dom-utils.js (element walking,
    boundary lookup, toFragment): the boundary receiver now uses the
    loader's TreeWalker walk instead of querySelectorAll("*"), and the
    receiver-vs-loader clone/adopt fork is an explicit clone option.
  • One owner for repeated micro-implementations: mergeFeatures (app.js
    createAppFeatureSet, previously copied byte-identical into three entry
    files), the component fragment comment-marker protocol (html.js, built by
    components and parsed by the loader), lazy-descriptor invocation
    (createLazyInvoker in lazy-registry.js, adopted by handlers, partials,
    components, and async signals), toError/errorMessage/reportUnhandled
    (errors.js, adopted by server, router, and the scheduler), and script-JSON
    plus attribute escaping (html.js, adopted by app.js SSR output).
    boundary-receiver.js and lazy-registry.js keep deliberately-commented
    local copies of toError/errorMessage so the stream slice stays free of
    the errors.js module.
  • Derived flow bridges (async-signal loading/error/ready/status/
    version metadata and computed refs) no longer serialize into page
    snapshots: they recompute on resume, and the .error metadata bridge
    previously embedded raw error objects in the page payload.
  • Fixed the inline swap-binding lifecycle: comparison renders (ifChanged,
    bind, swap-many snapshots) serialize binding values to stable tokens
    instead of minting registry ids — per-render ids embedded in snapshots
    made every comparison unequal, silently degrading dedupe to always-swap —
    and a boundary's committed render now tracks its minted ids and releases
    the previous content's ids on re-swap, so repeated swaps no longer grow
    the binding map for the loader's lifetime.
  • Owned schedulers (constructed by Loader and createApp) report job
    failures through the structured error pipeline: bindings, commits, and
    effects that fail now reach the configured onError and dispatch a
    cancelable async:error event on the job's element scope, instead of
    escaping straight to globalThis.reportError. Injected schedulers keep
    their creator's error wiring.
  • detachRoot(null) destroys a supplied loader that never registered into
    the root set (detach before start()), mirroring the guard destroy()
    already had.
  • Rendering an inline template binding without a Loader now throws the same
    clear error the component renderer raises, instead of silently emitting
    [object Object] into the attribute.
  • Completion and recovery hardening: completion jobs (awaited commits) reject
    their awaiter without double-reporting through the scheduler onError
    bridge; inline binding comparison tokens JSON-escape keys and leaves so
    differently-shaped values cannot collide into a skipped swap; a content
    retry now recovers an error-settled reveal index instead of rejecting as a
    double commit; the router facade restores the original ready()-resolution
    order; the registry store's introspection snapshot honors
    _snapshotExempt; the app-owned
    scheduler bridge reads runtime.onError at failure time.
  • Examples: the router example gains a "*" fallback route (first render no
    longer errors on the served URL); the ssr example resumes through the
    public readSnapshot(document) API; the streaming example now actually
    streams — out-of-order inline wire patches through
    AsyncStream.applyScript with reveal ordering, error settling, and
    recovery; new swap-dedupe example for ifChanged; partials README
    documents the runtime-capture pattern.
  • Production tests: a server-render → JSON wire → readSnapshot browser
    resume round trip (no partial, server function, or re-render on the
    browser side), and a progressive-document streaming flow (shuffled inline
    patches, buffering, error settle, recovery) run as part of the server and
    runtime suites.
  • Removed the dead scripts/release-doctor.js (superseded by
    async-pipeline release doctor); the examples scripts run the whole
    tests/examples/ suite; fixed the stale benchmarks/results/ ignore
    rule; stream scenario budgets carry working headroom (47500).
  • Updated the inlined Flow integration to @async/flow 0.10.5 for
    resume-safe async-signal snapshots and cross-copy compose stops.
  • Bundle size from bundled TypeScript source: browser.ts raw 279,370 B (279.4 KB / 0.279 MB), gzip 56,946 B (56.9 KB / 0.057 MB), br 46,741 B (46.7 KB / 0.047 MB) -> browser.min.js raw 114,724 B (114.7 KB / 0.115 MB), gzip 34,458 B (34.5 KB / 0.034 MB), br 30,253 B (30.3 KB / 0.030 MB); delta raw -164,646 B (-164.6 KB / -0.165 MB), gzip -22,488 B (-22.5 KB / -0.022 MB), br -16,488 B (-16.5 KB / -0.016 MB).

Release evidence

  • Release type: stable
  • Package profile: framework-browser
  • npm pack files: 63
File Raw Gzip Brotli
browser.d.ts 45.1 KB 8.2 KB 7.3 KB
browser.js 272.8 KB 55.9 KB 45.6 KB
browser.min.js 112.0 KB 33.7 KB 29.5 KB
browser.ts 272.8 KB 55.9 KB 45.6 KB
browser.umd.js 289.2 KB 57.0 KB 46.3 KB
browser.umd.min.js 113.7 KB 33.9 KB 29.6 KB
framework.d.ts 49.3 KB 9.0 KB 8.0 KB
framework.ts 429.4 KB 86.1 KB 68.4 KB
server.js 429.4 KB 86.0 KB 68.4 KB

Diff links:


Source: CHANGELOG.md in tag v0.19.1.