- Reveal commits are retry-safe after DOM or scheduler failures: failed patches can reuse their sequence, buffered siblings remain queued, and failed recovery keeps the settled-error marker until the replacement commits.
- Completion failures reject only their own waiter without dropping sibling work. Loader-owned, unobserved frame commits enter structured error reporting exactly once, while observed commits and injected schedulers retain their existing error ownership.
- Signal refs now retain registry provenance for inline bindings and
ifChangedsnapshots. Same-id refs from separate registries subscribe and compare independently, including composite bindings and legacy refs. - Removing an outer boundary now releases inline binding ids owned by nested boundaries instead of leaving stale values reachable by later scans.
- Updated the Framework integration to
@async/flow0.10.6. - Refreshed the two streaming scenario budgets to 48,000 B after the reviewed recovery and ownership fixes; current closures are 47,613 B and 47,679 B gzip.
- Bundle size from bundled TypeScript source:
browser.tsraw 281,608 B (281.6 KB / 0.282 MB), gzip 57,605 B (57.6 KB / 0.058 MB), br 47,220 B (47.2 KB / 0.047 MB) ->browser.min.jsraw 115,320 B (115.3 KB / 0.115 MB), gzip 34,608 B (34.6 KB / 0.035 MB), br 30,437 B (30.4 KB / 0.030 MB); delta raw -166,288 B (-166.3 KB / -0.166 MB), gzip -22,997 B (-23.0 KB / -0.023 MB), br -16,783 B (-16.8 KB / -0.017 MB).
- Fixed pre-runtime
app.applySnapshot(...): snapshots without aflowkey 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 tailvisible(normalized to "no tail treatment") instead of throwing. AsyncStreampatches 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
togethergroups commit buffered siblings instead of stalling forever. applyServerResultno longer blanks a boundary for envelopes withhtml: undefinedorstatus: 204, matching the router's swap accounting; the router now shares the exportedisServerEnvelopepredicate 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:xnow delegates to the shared class-token writer, removing a binding-key collision withclass:xthat 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:
parsePathin signals.js,isAsyncSignalSnapshotin app.js, and a no-op template branch in the loader's swap HTML renderer. - Centralized the typed-registry CRUD scaffolding
(
createTypedRegistryMethodsin 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
createPendingFacadeimplementation; per-facade differences (commit-await methods,_clearCurrentbatch 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 ofquerySelectorAll("*"), and the receiver-vs-loader clone/adopt fork is an explicitcloneoption. - One owner for repeated micro-implementations:
mergeFeatures(app.jscreateAppFeatureSet, 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 (createLazyInvokerin 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 oftoError/errorMessageso the stream slice stays free of the errors.js module. - Derived flow bridges (async-signal
loading/error/ready/status/versionmetadata and computed refs) no longer serialize into page snapshots: they recompute on resume, and the.errormetadata 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
LoaderandcreateApp) report job failures through the structured error pipeline: bindings, commits, and effects that fail now reach the configuredonErrorand dispatch a cancelableasync:errorevent on the job's element scope, instead of escaping straight toglobalThis.reportError. Injected schedulers keep their creator's error wiring. detachRoot(null)destroys a supplied loader that never registered into the root set (detach beforestart()), mirroring the guarddestroy()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
onErrorbridge; 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 readsruntime.onErrorat 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 publicreadSnapshot(document)API; the streaming example now actually streams — out-of-order inline wire patches throughAsyncStream.applyScriptwith reveal ordering, error settling, and recovery; new swap-dedupe example forifChanged; partials README documents the runtime-capture pattern. - Production tests: a server-render → JSON wire →
readSnapshotbrowser 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 byasync-pipeline release doctor); theexamplesscripts run the wholetests/examples/suite; fixed the stalebenchmarks/results/ignore rule; stream scenario budgets carry working headroom (47500). - Updated the inlined Flow integration to
@async/flow0.10.5 for resume-safe async-signal snapshots and cross-copy compose stops. - Bundle size from bundled TypeScript source:
browser.tsraw 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.jsraw 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).
- Added structured runtime diagnostics with stable error codes,
AsyncError,toAsyncDiagnostic(...), andonErrorownership across apps, loaders, and routers. Delegated and lifecycle failures now reach callbacks, cancelableasync:errorevents, or the platform unhandled-error path instead of disappearing. - Published the framework-native app authoring contract as package
AGENTS.md, added declarative component and app-composition examples, and added a repository gate that keeps public examples on framework-owned attachment, events, bindings, and boundary updates. - Updated
@async/flowto 0.10.4 and documented the Flow boundary: live Flow declarations materialize into ordinary framework registries, while portable machine plans remain optimizer input and do not introduce a separate runtime interpreter or slice. - Bundle size from bundled TypeScript source:
browser.tsraw 271,362 B (271.4 KB / 0.271 MB), gzip 52,388 B (52.4 KB / 0.052 MB), br 42,937 B (42.9 KB / 0.043 MB) ->browser.min.jsraw 113,880 B (113.9 KB / 0.114 MB), gzip 33,597 B (33.6 KB / 0.034 MB), br 29,462 B (29.5 KB / 0.029 MB); delta raw -157,482 B (-157.5 KB / -0.157 MB), gzip -18,791 B (-18.8 KB / -0.019 MB), br -13,475 B (-13.5 KB / -0.013 MB).
- Reorganized the README into a compact guide and moved the deeper material into focused docs for install/load, app registries, server calls, SSR activation, streaming boundaries, entrypoints, and Vite/Hono setup.
- Updated the layer docs and specs to use L0-L7 abstraction layers consistently, including clearer L0 server-led HTML, native forms/actions, and optional enhancement boundaries.
- Added
examples/hateoas-actions: a Hono-rendered HATEOAS account flow where links and native form verbs remain the source of truth, while Async enhances the returned fragments intoasync:boundaryswaps. - Bundle size from bundled TypeScript source:
browser.tsraw 261,003 B (261.0 KB / 0.261 MB), gzip 49,799 B (49.8 KB / 0.050 MB), br 41,084 B (41.1 KB / 0.041 MB) ->browser.min.jsraw 108,690 B (108.7 KB / 0.109 MB), gzip 31,875 B (31.9 KB / 0.032 MB), br 28,013 B (28.0 KB / 0.028 MB); delta raw -152,313 B (-152.3 KB / -0.152 MB), gzip -17,924 B (-17.9 KB / -0.018 MB), br -13,071 B (-13.1 KB / -0.013 MB).
- BREAKING: unified lifecycle vocabulary on "attach" and removed the "mount"
term everywhere.
loader.mount(...)and theAsync.loader.mount(...)facade are nowloader.attach(...)/Async.loader.attach(...); the rendered-componentmount(target)alias is gone (useattach(target));this.on("mount", ...)now throws (usethis.on("attach", ...)) and thethis.onMount(...)helper was removed (usethis.onAttach(...)); theon:mountmarkup alias no longer binds; stale markup logs a one-time removal warning. The Flow bridge feature keymountRegistrationsis nowattachRegistrations(attachFlowRegistrations). Specs, docs, and type declarations use attach terminology throughout. - Bundle size from bundled TypeScript source:
browser.tsraw 261,003 B (261.0 KB / 0.261 MB), gzip 49,799 B (49.8 KB / 0.050 MB), br 41,084 B (41.1 KB / 0.041 MB) ->browser.min.jsraw 108,690 B (108.7 KB / 0.109 MB), gzip 31,875 B (31.9 KB / 0.032 MB), br 28,013 B (28.0 KB / 0.028 MB); delta raw -152,313 B (-152.3 KB / -0.152 MB), gzip -17,924 B (-17.9 KB / -0.018 MB), br -13,071 B (-13.1 KB / -0.013 MB).
- Memoized boundary-element lookup in the loader:
loader.swap(...)resolved its boundary id by walking the entire document on every swap (visible as a full-document traversal per History selection); the element is now cached weakly per id and re-resolved only when it leaves the document or loses its boundary id. - Activation now scans a scope with a single tree traversal: pseudo-event dispatch (attach/visible/intersect) reuses the shared element collection instead of a second walk. Component-mounted children keep their own nested scan.
- The Vite plugin excludes the framework entrypoints from
optimizeDeps(opt out withoptimizeFrameworkDeps: true): the published entrypoints are flat ESM bundles, and Vite's prebundle cache does not watchfile:/link:dependency contents — local framework rebuilds were served stale untilnode_modules/.vitewas deleted by hand. - Navigation failures from intercepted links, forms, and history events are
now logged with
console.error(they have no caller to reject to), and unmatched navigation withoutfallback: "document"logs aconsole.warnwith guidance — previously both failed silently. - Added a commit stall watchdog:
loader._whenCommitted(...)warns (commitStallWarningMs, default 2000ms,0/falsedisables) when a boundary commit has not settled, naming the await-inside-scheduler.batchdeadlock composition so it is diagnosable instead of a silent freeze. router.prefetch(...)onserver: trueroutes now caches the fetched envelope briefly (prefetchTtlMsoption, default 5000ms); the next navigation with a matching URL and boundary consumes it single-use instead of refetching.- Added
tests/performance/: deterministic hot-path performance contracts (activation scan traversal counts, attribute-config memoization, swap rescan scoping, scheduler/signal write coalescing, single frame wait per commit batch, router fast-path work counts) plus a hot-path registry (tests/performance/hot-paths.json). A coverage guardrail keeps the registry, the// @hot-paths:headers in contract tests, and thetest.performancepipeline task inputs in sync, so changes to a registered hot-path source automatically re-run the suite. The swap-rescan contracts caught the boundary-lookup walk fixed above. - Categorized the test tree into suites —
tests/unit/,tests/runtime/,tests/router/,tests/server/,tests/timing/,tests/performance/,tests/build/, andtests/examples/— with matchingtest:<suite>scripts (seetests/README.md). Added a dedicatedtests/timing/suite covering rendering andrequestAnimationFramegotchas under explicit frame-timed schedulers: suspended-frame fallbacks, exactly-once frame/fallback races, FIFO commit ordering, commits scheduled inside open batches, loader swaps with rebinding and ordering, handler-initiated swaps, signal/swap coalescing, and router navigation (local partials, server partials with sub-boundaries, suspended frames, popstate). - Bundle size from bundled TypeScript source:
browser.tsraw 261,577 B (261.6 KB / 0.262 MB), gzip 50,018 B (50.0 KB / 0.050 MB), br 41,211 B (41.2 KB / 0.041 MB) ->browser.min.jsraw 108,975 B (109.0 KB / 0.109 MB), gzip 32,004 B (32.0 KB / 0.032 MB), br 28,111 B (28.1 KB / 0.028 MB); delta raw -152,602 B (-152.6 KB / -0.153 MB), gzip -18,014 B (-18.0 KB / -0.018 MB), br -13,100 B (-13.1 KB / -0.013 MB).
- Added server route partials:
defineRoute({ server: true })makes CSR/SPA navigation fetch the target URL withAccept: application/x-async-partial(plus anx-async-boundaryrequest header naming the boundary the transition plan wants filled) and apply the returned wire server envelope ({ __async_server_result__: 1, html, signals, cache, boundary, redirect, title }) through the existing navigation pipeline. HTTP redirects followed by the fetch update router state, the route snapshot, and browser history to the final URL.createRouter(...)accepts afetchoption to override the window fetch (tests, custom transports); ambientglobalThis.fetchis never used.prefetch(...)returns the fetched envelope without applying it. - Added a router
fallbackoption ("error"default,"document"): withfallback: "document", unmatched navigation in client modes performs native document navigation instead of dead-ending inrouter.error, enabling incremental SPA adoption over server-rendered apps. Assigning the current browser URL is refused to prevent reload loops. Server-partial responses that are not envelopes (or fail) also fall back to document navigation in this mode. - Added
render: "document"route definitions: matched routes can force native document navigation (downloads, raw endpoints) while staying registered. - Added multi-segment splat patterns:
/:org/:name/tree/*restcaptures the remaining segments (decoded per segment) asparams.rest. Splat segments must terminate the pattern and rank above*wildcard routes and below single-segment params. - Added master-detail navigation:
viewKeymay now be a function of the route match, and routes may declaresubBoundary. A same-view navigation (same computedviewKey) on a route withsubBoundaryrenders/fetches into that nested boundary instead of going state-only, so query-driven detail panes (e.g.?commit=<sha>) swap without touching the surrounding view. Route snapshots keep comparing view identity on the route-level boundary. - Partial results with a string
titlenow updatedocument.title, and client navigations that swapped content scroll to the top (or to the URL hash target) unless the router is created withscroll: false. Async.start(...)now forwardsurlMode,fallback, andscrollto the runtime router and accepts arouterOptionsobject for the remainingcreateRouter(...)options.- Server runtime
render(url, { document: false })returns the raw route fragment without the boundary section or snapshot script, for building server route partial envelopes whose swap target is an already-activated document. - Fixed a navigation deadlock in CSR/SPA modes with frame-timed commits (real
browsers):
applyNavigationResultawaited boundary commit completion insidescheduler.batch(...), where automatic flushes are suppressed, so route swaps could stall indefinitely and never updatedocument.title, history, orrouter.pending. Commit awaits now happen outside the batch. Node test environments commit synchronously, which is why the suite never caught it; new regression tests force frame timing. - Frame-timed commits now race the animation frame against a timeout
(
frameFallbackMs, default 50ms): browsers suspendrequestAnimationFramein hidden tabs, which froze boundary commits — and anything awaiting them, including router navigation — until the tab became visible again. Visible tabs stay frame-aligned; hidden tabs fall back to timer cadence. - Bundle size from bundled TypeScript source:
browser.tsraw 259,693 B (259.7 KB / 0.260 MB), gzip 49,336 B (49.3 KB / 0.049 MB), br 40,621 B (40.6 KB / 0.041 MB) ->browser.min.jsraw 108,501 B (108.5 KB / 0.109 MB), gzip 31,770 B (31.8 KB / 0.032 MB), br 27,913 B (27.9 KB / 0.028 MB); delta raw -151,192 B (-151.2 KB / -0.151 MB), gzip -17,566 B (-17.6 KB / -0.018 MB), br -12,708 B (-12.7 KB / -0.013 MB).
- Memoized attribute-prefix normalization by config identity so activation scans reuse normalized attribute config on the hot path instead of re-normalizing prefixes for every attribute read.
- Reworked loader activation to collect each scan scope once with a TreeWalker, share that element list across revive, signal, class, event, boundary, and component passes, and merge attach, visible, and intersect pseudo-event binding into one pass.
- Bundle size from bundled TypeScript source:
browser.tsraw 258,315 B (258.3 KB / 0.258 MB), gzip 48,822 B (48.8 KB / 0.049 MB), br 40,208 B (40.2 KB / 0.040 MB) ->browser.min.jsraw 108,261 B (108.3 KB / 0.108 MB), gzip 31,669 B (31.7 KB / 0.032 MB), br 27,814 B (27.8 KB / 0.028 MB); delta raw -150,054 B (-150.1 KB / -0.150 MB), gzip -17,153 B (-17.2 KB / -0.017 MB), br -12,394 B (-12.4 KB / -0.012 MB).
- Expanded
@async/framework/flow(and the main entry) to re-export the complete@async/flowhelper surface: step helpers (dispatch,after,branch,guard,transition), condition helpers (bool,every,some,not,can,matches,inspect), composition (compose,parallel,remember), and theflowStatusdeclaration helper, alongside the existingset,update,when, andonError. Apps can author full Flow definitions without installing@async/flowdirectly. - Removed the per-notification random dedupe key from the Flow scheduler bridge. Keys added keyed-job bookkeeping for every Flow notification without ever deduping, and a key collision could silently drop a notification.
- Dropped the stale
@async/flow/runmodule mapping from the bundle scripts (@async/flow/runis not a public Flow subpath) and added the@async/flow/composemapping used by the expanded flow entry.
- Updated the Flow bridge to consume
@async/flow0.10.3, including the framework-runtime helper paths required by current Flow releases. - Fixed Flow async signal refresh handlers so a refresh without authored input uses the signal's configured arguments instead of passing an empty object.
- Rolled back partial signal and handler registrations when a Flow mount fails, preventing failed mounts from leaving stale registry entries behind.
- Fixed SSR signal patches for mounted Flow signals so exact paths such as
cart.totalupdate without serializing an unintended parentcartsignal. - Added
./jsx/jsx-runtimeand./jsx/jsx-dev-runtimepackage exports sojsxImportSource: "@async/framework/jsx"resolves under the automatic JSX transform; the base entrypoints default to the runtime profile types. - Guarded the Vite plugin bootstrap transform: modules are replaced only when
they actually import
@async/framework/jsx*(comment and string mentions no longer match), replacements are logged, multiple modules collapsed into one virtual bootstrap now warn, and full-rewrite transforms return an empty sourcemap instead ofmap: null. - Made the Vite 8 + Rolldown host check use plugin-context metadata
(
this.meta.viteVersion/this.meta.rolldownVersion) inconfigResolvedinstead of treating the resolved config as a host descriptor, and exporteddetectViteHostandimportsAsyncJsxhelpers. - Stopped defaulting
server.basewhen composing@hono/vite-dev-server;baseis forwarded only when the app sets it, so user-configured Vitebasevalues are no longer overridden by default. - Declared
vite >= 8as an optional peer dependency. - Reported runtime slice
status(availableforsignals/events,plannedforasync-signals/stream) with aruntime-slice-plannedwarning diagnostic, and documented that planned slices are recorded but not activated by@async/framework/runtimeyet. - Reworked the
vite-jsx-streamingexample onto the buildtime JSX profile so the authoring source matches the shipped type profiles, and documented that the fixture profile is the current source of truth for the emitted plan.
- Added scheduler commit-phase ordering for app-level loader swaps and streamed boundary patches, including frame-backed commits and deterministic non-browser fallbacks.
- Added declaration conventions for
Async.use(...)so registered kinds can materialize on register, start, or demand under configurable duplicate policies. - Bundle size from bundled TypeScript source:
browser.tsraw 255,782 B (255.8 KB / 0.256 MB), gzip 47,724 B (47.7 KB / 0.048 MB), br 39,343 B (39.3 KB / 0.039 MB) ->browser.min.jsraw 107,826 B (107.8 KB / 0.108 MB), gzip 31,527 B (31.5 KB / 0.032 MB), br 27,717 B (27.7 KB / 0.028 MB); delta raw -147,956 B (-148.0 KB / -0.148 MB), gzip -16,197 B (-16.2 KB / -0.016 MB), br -11,626 B (-11.6 KB / -0.012 MB).
- Updated the Flow bridge to consume
@async/flow0.10.0 through the scheduler-free integration subpaths and shared protocol brands. - Bundle size from bundled TypeScript source:
browser.tsraw 236,170 B (236.2 KB / 0.236 MB), gzip 44,028 B (44.0 KB / 0.044 MB), br 36,421 B (36.4 KB / 0.036 MB) ->browser.min.jsraw 99,320 B (99.3 KB / 0.099 MB), gzip 29,136 B (29.1 KB / 0.029 MB), br 25,662 B (25.7 KB / 0.026 MB); delta raw -136,850 B (-136.9 KB / -0.137 MB), gzip -14,892 B (-14.9 KB / -0.015 MB), br -10,759 B (-10.8 KB / -0.011 MB).
- Moved streaming, Flow, and router browser code behind explicit
@async/framework/stream,@async/framework/flow, and@async/framework/routersubpaths so the default browser asset stays focused on the core runtime. - Added guarded Flow and router startup errors when default-browser apps use those declarations without importing their opt-in subpath.
- Added a bundle optimizer pipeline for Brotli-oriented candidate measurement and diagnostics.
- Bundle size from bundled TypeScript source:
browser.tsraw 227,580 B (227.6 KB / 0.228 MB), gzip 42,303 B (42.3 KB / 0.042 MB), br 35,028 B (35.0 KB / 0.035 MB) ->browser.min.jsraw 95,660 B (95.7 KB / 0.096 MB), gzip 27,847 B (27.8 KB / 0.028 MB), br 24,709 B (24.7 KB / 0.025 MB); delta raw -131,920 B (-131.9 KB / -0.132 MB), gzip -14,456 B (-14.5 KB / -0.014 MB), br -10,319 B (-10.3 KB / -0.010 MB).
- Added the app-level
Async.routerfacade with queuednavigate,prefetch,ready,match, and nestedloaderaccess before runtime startup. - Added router transition planning that skips duplicate active-route work and
uses signal-only updates for same-view navigation unless
force: trueis requested. - Made
createRouter(...)start immediately, rejected separate signal registry injection, and kept route and partial registration on the app registry path. - Documented routing layers from simple
Async.use({ route, partial })setup through signal-router dashboards, refresh scopes, and custom runtime wiring. - Bundle size from bundled TypeScript source:
browser.tsraw 366,552 B (366.6 KB / 0.367 MB), gzip 67,930 B (67.9 KB / 0.068 MB), br 55,263 B (55.3 KB / 0.055 MB) ->browser.min.jsraw 153,961 B (154.0 KB / 0.154 MB), gzip 44,479 B (44.5 KB / 0.044 MB), br 38,561 B (38.6 KB / 0.039 MB); delta raw -212,591 B (-212.6 KB / -0.213 MB), gzip -23,451 B (-23.5 KB / -0.023 MB), br -16,702 B (-16.7 KB / -0.017 MB).
- Added
asyncFramework({ layer, server, client })for Hono-backed Vite development and client-only production asset builds without a platform target. - Added Vite Hono and Vite JSX streaming examples, including optimizer report
visibility for the selected
signals,events,async-signals, andstreamruntime slices. - Re-exported the optimizer
reportfrom Vite-generated JSX bootstrap modules and marked runtime handler imports for Vite analysis so example dev servers stay warning-free. - Bundle size from bundled TypeScript source:
browser.tsraw 356,171 B (356.2 KB / 0.356 MB), gzip 66,646 B (66.6 KB / 0.067 MB), br 54,356 B (54.4 KB / 0.054 MB) ->browser.min.jsraw 149,871 B (149.9 KB / 0.150 MB), gzip 43,590 B (43.6 KB / 0.044 MB), br 37,839 B (37.8 KB / 0.038 MB); delta raw -206,300 B (-206.3 KB / -0.206 MB), gzip -23,056 B (-23.1 KB / -0.023 MB), br -16,517 B (-16.5 KB / -0.017 MB).
- Added
loader.swap({ type: "many", ifChanged: true })to skip unchanged per-boundary replacement inside batched swaps. - Added
loader.defineRefreshPlan(...)andloader.refresh(scope)for declarative scope-to-boundary refresh orchestration in signal-router SPAs. - Added
loader.swap({ type: "bind", deps: [...] })for explicit signal-path refresh dependencies instead of implicit render-time collection. - Added per-entry
{ html, strategy, attach }objects intype: "many"updates for mixed morph/replace batches. - Added morph
attach: "preserve"(default) andattach: "rebind"options, plus a development warning when morph preserves anon:attachnode but removes listener-bearing descendants. - Bundle size from bundled TypeScript source:
browser.tsraw 356,171 B (356.2 KB / 0.356 MB), gzip 66,646 B (66.6 KB / 0.067 MB), br 54,356 B (54.4 KB / 0.054 MB) ->browser.min.jsraw 149,871 B (149.9 KB / 0.150 MB), gzip 43,590 B (43.6 KB / 0.044 MB), br 37,839 B (37.8 KB / 0.038 MB); delta raw -206,300 B (-206.3 KB / -0.206 MB), gzip -23,056 B (-23.1 KB / -0.023 MB), br -16,517 B (-16.5 KB / -0.017 MB).
- Treat route partials that return
status: 204, nohtmlkey, barenull, or bareundefinedas no-op route HTML updates instead of clearing or stringifying the active boundary. - Added config-first
loader.swap({ type })variants for unchanged-aware, batched, and signal-bound boundary refreshes without expanding the loader method surface. - Bundle size from bundled TypeScript source:
browser.tsraw 348,555 B (348.6 KB / 0.349 MB), gzip 65,264 B (65.3 KB / 0.065 MB), br 53,133 B (53.1 KB / 0.053 MB) ->browser.min.jsraw 146,383 B (146.4 KB / 0.146 MB), gzip 42,600 B (42.6 KB / 0.043 MB), br 37,056 B (37.1 KB / 0.037 MB); delta raw -202,172 B (-202.2 KB / -0.202 MB), gzip -22,664 B (-22.7 KB / -0.023 MB), br -16,077 B (-16.1 KB / -0.016 MB).
- Added
createRouter({ mode: "signals" })for route-only shells that updaterouter.*state and history without rendering partials or swapping boundaries. - Added
loader.swap(boundary, html, { scan })withauto,full, andnonescan modes for cheaper boundary replacement when inserted content is inert or manually scanned later. - Added
loader.swap(boundary, html, { strategy: "morph" })as an opt-in stable-shell update path that preserves matching nodes, avoids full subtree replacement, and still cleans removed or replaced scoped resources. - Treat partial envelopes with
html: undefinedas no route replacement and warn instead of clearing the active route boundary;html: ""remains an explicit clear. - Scoped lifecycle fallback hooks for components rendered through
this.render(...)sothis.onMount(...),this.onVisible(...), andthis.on("intersect", ...)target the child component's rendered root instead of the ancestor mount root. - Preserved direct
loader.mount(target, Component)fallback behavior, where rootless and multi-root top-level components still receive the mount target. - Updated the bundled Flow bridge to
@async/flow@0.5.0, using async signal detection while preserving existing async signal metadata and refresh paths. - Migration note: code that intentionally used nested fallback hooks to mutate
the ancestor mount root should move that behavior to the ancestor component or
bind a specific element with
on:attach. - Added
this.onAttach(fn)as the canonical component attach lifecycle helper, withthis.onMount(fn),this.on("mount", ...), andon:mountretained as compatibility aliases that warn about the rename. - Bundle size from bundled TypeScript source:
browser.tsraw 338,346 B (338.3 KB / 0.338 MB), gzip 63,620 B (63.6 KB / 0.064 MB), br 51,844 B (51.8 KB / 0.052 MB) ->browser.min.jsraw 142,172 B (142.2 KB / 0.142 MB), gzip 41,549 B (41.5 KB / 0.042 MB), br 36,106 B (36.1 KB / 0.036 MB); delta raw -196,174 B (-196.2 KB / -0.196 MB), gzip -22,071 B (-22.1 KB / -0.022 MB), br -15,738 B (-15.7 KB / -0.016 MB).
- Scoped lifecycle fallback hooks for components rendered through
this.render(...)sothis.onMount(...),this.onVisible(...), andthis.on("intersect", ...)target the child component's rendered root instead of the ancestor mount root. - Preserved direct
loader.mount(target, Component)fallback behavior, where rootless and multi-root top-level components still receive the mount target. - Updated the bundled Flow bridge to
@async/flow@0.5.0, using async signal detection while preserving existing async signal metadata and refresh paths. - Migration note: code that intentionally used nested fallback hooks to mutate
the ancestor mount root should move that behavior to the ancestor component or
bind a specific element with
on:attach. - Bundle size from bundled TypeScript source:
browser.tsraw 327,212 B (327.2 KB / 0.327 MB), gzip 61,393 B (61.4 KB / 0.061 MB), br 50,139 B (50.1 KB / 0.050 MB) ->browser.min.jsraw 138,257 B (138.3 KB / 0.138 MB), gzip 40,337 B (40.3 KB / 0.040 MB), br 35,071 B (35.1 KB / 0.035 MB); delta raw -188,955 B (-189.0 KB / -0.189 MB), gzip -21,056 B (-21.1 KB / -0.021 MB), br -15,068 B (-15.1 KB / -0.015 MB).
- Scoped lifecycle fallback hooks for components rendered through
this.render(...)sothis.onMount(...),this.onVisible(...), andthis.on("intersect", ...)target the child component's rendered root instead of the ancestor mount root. - Preserved direct
loader.mount(target, Component)fallback behavior, where rootless and multi-root top-level components still receive the mount target. - Updated the bundled Flow bridge to
@async/flow@0.5.0, using async signal detection while preserving existing async signal metadata and refresh paths. - Migration note: code that intentionally used nested fallback hooks to mutate
the ancestor mount root should move that behavior to the ancestor component or
bind a specific element with
on:attach. - Bundle size from bundled TypeScript source:
browser.tsraw 327,212 B (327.2 KB / 0.327 MB), gzip 61,393 B (61.4 KB / 0.061 MB), br 50,139 B (50.1 KB / 0.050 MB) ->browser.min.jsraw 138,257 B (138.3 KB / 0.138 MB), gzip 40,337 B (40.3 KB / 0.040 MB), br 35,071 B (35.1 KB / 0.035 MB); delta raw -188,955 B (-189.0 KB / -0.189 MB), gzip -21,056 B (-21.1 KB / -0.021 MB), br -15,068 B (-15.1 KB / -0.015 MB).
- Added the Markdown-backed GitHub Pages docs app with hash routes, command search, grouped navigation, article content, and an on-page heading rail.
- Added
createRouter({ urlMode: "hash" })for static-host routes such as#/docs/getting-startedwhile preserving ordinary section anchors. - Added publish-package
typesandsourcemetadata for API indexers while preserving the existing export-map declarations. - Renamed build optimizer signal source output from
derivedandasyncto the public-facingcomputedandasyncSignalintent names. - Kept event normalization ahead of signal classification and runtime-slice selection in the optimizer artifact order.
- Updated optimizer artifact, runtime selection, build profile, and signal classification tests to prove computed and async signal reporting, ownership diagnostics, maybe-promise rejection, runtime slice selection, and bootstrap report parity.
- Bundle size from bundled TypeScript source:
browser.tsraw 274,307 B (274.3 KB / 0.274 MB), gzip 52,238 B (52.2 KB / 0.052 MB), br 42,841 B (42.8 KB / 0.043 MB) ->browser.min.jsraw 116,507 B (116.5 KB / 0.117 MB), gzip 34,553 B (34.6 KB / 0.035 MB), br 30,179 B (30.2 KB / 0.030 MB); delta raw -157,800 B (-157.8 KB / -0.158 MB), gzip -17,685 B (-17.7 KB / -0.018 MB), br -12,662 B (-12.7 KB / -0.013 MB).
- Added a profile-aware event normalization artifact before signal
classification so JSX-native event props and protocol event props lower to
canonical
on:event records. - Preserved source event prop spelling in optimizer diagnostics while accepting protocol event props only for runtime or compatibility profiles.
- Added duplicate canonical event diagnostics so mixed
onClickandon:clickdeclarations cannot silently overwrite each other. - Kept handler emission independent from source prop spelling by feeding canonical protocol records into the handler planning pass.
- Bundle size from bundled TypeScript source:
browser.tsraw 231,217 B (231.2 KB / 0.231 MB), gzip 44,078 B (44.1 KB / 0.044 MB), br 36,392 B (36.4 KB / 0.036 MB) ->browser.min.jsraw 98,972 B (99.0 KB / 0.099 MB), gzip 29,418 B (29.4 KB / 0.029 MB), br 25,930 B (25.9 KB / 0.026 MB); delta raw -132,245 B (-132.2 KB / -0.132 MB), gzip -14,660 B (-14.7 KB / -0.015 MB), br -10,462 B (-10.5 KB / -0.010 MB).
- Added the composition pattern catalog covering default children, named regions, scoped content templates, presenter component props, dynamic outlets, boundaries, and anti-patterns.
- Separated L1 and L2 examples for each composition pattern and marked planned source forms so released behavior is distinct from future build-required syntax.
- Added out-of-order streaming guidance for every composition pattern, including boundary placement, independent commits, same-boundary sequencing, and rescanning inserted streamed HTML.
- Bundle size from bundled TypeScript source:
browser.tsraw 231,217 B (231.2 KB / 0.231 MB), gzip 44,078 B (44.1 KB / 0.044 MB), br 36,392 B (36.4 KB / 0.036 MB) ->browser.min.jsraw 98,972 B (99.0 KB / 0.099 MB), gzip 29,418 B (29.4 KB / 0.029 MB), br 25,930 B (25.9 KB / 0.026 MB); delta raw -132,245 B (-132.2 KB / -0.132 MB), gzip -14,660 B (-14.7 KB / -0.015 MB), br -10,462 B (-10.5 KB / -0.010 MB).
- Added a build-optimizer children-fragment lowering artifact for JSX nested children, recording empty, static, and lazy fragment output without retaining production JSX node arrays.
- Added diagnostics for authored
childrenprops, mixed explicit and nested children sources, runtime JSX children arrays, and unknown child-fragment resourcefulness before optimizer output is trusted. - Added optimizer fixtures and report counts covering static children, component/signal/event-bearing lazy children, and invalid children sources.
- Bundle size from bundled TypeScript source:
browser.tsraw 231,217 B (231.2 KB / 0.231 MB), gzip 44,078 B (44.1 KB / 0.044 MB), br 36,392 B (36.4 KB / 0.036 MB) ->browser.min.jsraw 98,972 B (99.0 KB / 0.099 MB), gzip 29,418 B (29.4 KB / 0.029 MB), br 25,930 B (25.9 KB / 0.026 MB); delta raw -132,245 B (-132.2 KB / -0.132 MB), gzip -14,660 B (-14.7 KB / -0.015 MB), br -10,462 B (-10.5 KB / -0.010 MB).
- Added explicit
<template async:children>capture for registeredasync:componenthosts, passing captured content through the same scoped default-children fragment contract asthis.render(...). - Added loader coverage proving explicit template children render only when consumed, ordinary host content is not implicitly captured, inserted protocol attributes are rescanned, and invalid or duplicate children templates fail.
- Documented the no-build template children contract in the README, DOM protocol spec, and component-system spec.
- Bundle size from bundled TypeScript source:
browser.tsraw 231,217 B (231.2 KB / 0.231 MB), gzip 44,078 B (44.1 KB / 0.044 MB), br 36,392 B (36.4 KB / 0.036 MB) ->browser.min.jsraw 98,972 B (99.0 KB / 0.099 MB), gzip 29,418 B (29.4 KB / 0.029 MB), br 25,930 B (25.9 KB / 0.026 MB); delta raw -132,245 B (-132.2 KB / -0.132 MB), gzip -14,660 B (-14.7 KB / -0.015 MB), br -10,462 B (-10.5 KB / -0.010 MB).
- Added scoped default children fragments for
this.render(Component, props, children), including lazy children factories, single-consumption checks, and duplicate source validation. - Added component tests proving static children, lazy nested component children, escaped string children, duplicate children errors, and cleanup for handlers and signals created while rendering children.
- Updated framework declarations and type fixtures so components can type
optional
Childrenprops while callers use the third render argument instead of authoringprops.children. - Documented the released default-children contract in the component README and component-system spec while keeping slots as the post-mount replacement primitive.
- Bundle size from bundled TypeScript source:
browser.tsraw 230,250 B (230.3 KB / 0.230 MB), gzip 43,813 B (43.8 KB / 0.044 MB), br 36,215 B (36.2 KB / 0.036 MB) ->browser.min.jsraw 98,493 B (98.5 KB / 0.098 MB), gzip 29,286 B (29.3 KB / 0.029 MB), br 25,793 B (25.8 KB / 0.026 MB); delta raw -131,757 B (-131.8 KB / -0.132 MB), gzip -14,527 B (-14.5 KB / -0.015 MB), br -10,422 B (-10.4 KB / -0.010 MB).
- Added first-class JSX type profiles for runtime/no-build and
buildtime/build-required authoring, including profile-local automatic
jsx-runtimeandjsx-dev-runtimepackage subpaths. - Added TypeScript fixtures proving runtime JSX accepts protocol attributes, strict buildtime JSX rejects protocol props, and both profiles avoid global ambient JSX pollution.
- Added component registry mounting through
async:componentplusthis.slot(...)outlets for child component replacement from signal-derived props. - Added example README coverage and clarified benchmark smoke checks without publishing an incomplete Vite optimizer setup as a public example.
- Bundle size from bundled TypeScript source:
browser.tsraw 228,180 B (228.2 KB / 0.228 MB), gzip 43,390 B (43.4 KB / 0.043 MB), br 35,878 B (35.9 KB / 0.036 MB) ->browser.min.jsraw 97,570 B (97.6 KB / 0.098 MB), gzip 29,015 B (29.0 KB / 0.029 MB), br 25,549 B (25.5 KB / 0.026 MB); delta raw -130,610 B (-130.6 KB / -0.131 MB), gzip -14,375 B (-14.4 KB / -0.014 MB), br -10,329 B (-10.3 KB / -0.010 MB).
- Updated framework release automation to consume
@async/pipeline@0.9.25, whose generated release workflow runs package-owned release evidence before release plan/inspect/changelog/notes steps sodist/exists before package inspection. - Kept release-description sync checks on the released pipeline path after the
existing
v0.11.20andv0.11.21GitHub Release description repairs. - Bundle size from bundled TypeScript source:
browser.tsraw 221,403 B (221.4 KB / 0.221 MB), gzip 42,093 B (42.1 KB / 0.042 MB), br 34,797 B (34.8 KB / 0.035 MB) ->browser.min.jsraw 95,027 B (95.0 KB / 0.095 MB), gzip 28,145 B (28.1 KB / 0.028 MB), br 24,793 B (24.8 KB / 0.025 MB); delta raw -126,376 B (-126.4 KB / -0.126 MB), gzip -13,948 B (-13.9 KB / -0.014 MB), br -10,004 B (-10.0 KB / -0.010 MB).
- Updated framework release automation to consume
@async/pipeline@0.9.24, whose generated release helper steps usepnpm dlxfor the pinned@async/releasepackage on Node 24/npm 11 runners. - Kept release-description sync scripts and generated workflow entries on the released pipeline path.
- Bundle size from bundled TypeScript source:
browser.tsraw 221,403 B (221.4 KB / 0.221 MB), gzip 42,093 B (42.1 KB / 0.042 MB), br 34,797 B (34.8 KB / 0.035 MB) ->browser.min.jsraw 95,027 B (95.0 KB / 0.095 MB), gzip 28,145 B (28.1 KB / 0.028 MB), br 24,793 B (24.8 KB / 0.025 MB); delta raw -126,376 B (-126.4 KB / -0.126 MB), gzip -13,948 B (-13.9 KB / -0.014 MB), br -10,004 B (-10.0 KB / -0.010 MB).
- Updated framework release automation to consume
@async/pipeline@0.9.22with the releasedrelease sync-descriptionscommand. - Added framework package scripts for release-description sync checks and
generated matching
pipeline:release:sync-descriptionsentries. - Synced existing semver GitHub Release descriptions from
CHANGELOG.mdso the changelog remains the source of truth. - Bundle size from bundled TypeScript source:
browser.tsraw 221,403 B (221.4 KB / 0.221 MB), gzip 42,093 B (42.1 KB / 0.042 MB), br 34,797 B (34.8 KB / 0.035 MB) ->browser.min.jsraw 95,027 B (95.0 KB / 0.095 MB), gzip 28,145 B (28.1 KB / 0.028 MB), br 24,793 B (24.8 KB / 0.025 MB); delta raw -126,376 B (-126.4 KB / -0.126 MB), gzip -13,948 B (-13.9 KB / -0.014 MB), br -10,004 B (-10.0 KB / -0.010 MB).
- Added the first build-required profile subpaths,
@async/framework/jsxand@async/framework/vite, with package export, declaration, pack, and installed-package coverage. - Added JSX authoring markers for
signal,component,Suspense, andRevealthat stay inert for compiler analysis instead of executing app code. - Added a Vite 8+ Rolldown plugin spike that emits a deterministic virtual runtime plan/report from fixture metadata and rejects unsupported hosts before transform output is trusted.
- Added the build-profile report fixture proving selected runtime slices,
omitted no-build systems, visible fallbacks, signal/event/stream counts, and
generated locator counts without importing the root
Asyncapp hub. - Bundle size from bundled TypeScript source:
browser.tsraw 221,403 B (221.4 KB / 0.221 MB), gzip 42,093 B (42.1 KB / 0.042 MB), br 34,797 B (34.8 KB / 0.035 MB) ->browser.min.jsraw 95,027 B (95.0 KB / 0.095 MB), gzip 28,145 B (28.1 KB / 0.028 MB), br 24,793 B (24.8 KB / 0.025 MB); delta raw -126,376 B (-126.4 KB / -0.126 MB), gzip -13,948 B (-13.9 KB / -0.014 MB), br -10,004 B (-10.0 KB / -0.010 MB).
- Added inert build optimizer artifact helpers for ADR 26 pass records, diagnostics, runtime slice selection, handler emission, and development report generation.
- Added optimizer fixtures for signal source classification, signal ownership, JSX event symbol extraction, Suspense/Reveal lowering, runtime selection, and server-only browser import diagnostics.
- Added build optimizer tests proving maybe-promise signals fail explicitly, event handlers are not forced through dynamic imports, Reveal ordering is deterministic, omitted runtime systems are visible, and helpers do not execute app modules or import no-build runtime systems.
- Bundle size from bundled TypeScript source:
browser.tsraw 221,403 B (221.4 KB / 0.221 MB), gzip 42,093 B (42.1 KB / 0.042 MB), br 34,797 B (34.8 KB / 0.035 MB) ->browser.min.jsraw 95,027 B (95.0 KB / 0.095 MB), gzip 28,145 B (28.1 KB / 0.028 MB), br 24,793 B (24.8 KB / 0.025 MB); delta raw -126,376 B (-126.4 KB / -0.126 MB), gzip -13,948 B (-13.9 KB / -0.014 MB), br -10,004 B (-10.0 KB / -0.010 MB).
- Added the stream backpatch protocol to
createBoundaryReceiver(...)with strictattrsvalidation for built numeric triples and no-build named tuples. - Added pending-slot replacement and reveal coordination for
as-ready,forwards,backwards, andtogetherstream groups, including collapsed and hidden tail visibility handling. - Added the
AsyncStreambrowser helper for no-build JSON stream patches, template replacement, configureddata-async-*attributes, and direct-child reveal metadata synthesis. - Added stream backpatch scenario-size coverage and updated browser scenario budgets for the expanded public stream surface.
- Bundle size from bundled TypeScript source:
browser.tsraw 221,403 B (221.4 KB / 0.221 MB), gzip 42,093 B (42.1 KB / 0.042 MB), br 34,797 B (34.8 KB / 0.035 MB) ->browser.min.jsraw 95,027 B (95.0 KB / 0.095 MB), gzip 28,145 B (28.1 KB / 0.028 MB), br 24,793 B (24.8 KB / 0.025 MB); delta raw -126,376 B (-126.4 KB / -0.126 MB), gzip -13,948 B (-13.9 KB / -0.014 MB), br -10,004 B (-10.0 KB / -0.010 MB).
- Added runtime slice entrypoints for
@async/framework/runtime,@async/framework/runtime/signals, and@async/framework/runtime/events. - Added generated package artifacts and installed-package coverage for runtime slice subpaths.
- Added deterministic scenario-size fixtures and checks for runtime, router, server-call, and boundary receiver examples.
- Added package-owned release evidence checks before release ensure so generated release workflows verify bundle and scenario evidence before publishing.
- Bundle size from bundled TypeScript source:
browser.tsraw 197,173 B (197.2 KB / 0.197 MB), gzip 37,198 B (37.2 KB / 0.037 MB), br 30,914 B (30.9 KB / 0.031 MB) ->browser.min.jsraw 84,013 B (84.0 KB / 0.084 MB), gzip 24,894 B (24.9 KB / 0.025 MB), br 22,079 B (22.1 KB / 0.022 MB); delta raw -113,160 B (-113.2 KB / -0.113 MB), gzip -12,304 B (-12.3 KB / -0.012 MB), br -8,835 B (-8.8 KB / -0.009 MB).
- Made the source package private and kept its public surface to the minimal
export spec for root,
/browser,/server, and/package.jsononly. - Moved publish staging to generated
dist/package.jsonso npm and release automation publish fromdist/while package consumers still receive root-level artifacts withoutdist/paths. - Removed legacy direct artifact subpath exports plus top-level
main/module/browser/typesand generated file lists from the source manifest. - Updated pack, size, pipeline, and installed-package coverage to verify the browser and server entrypoints remain split after packing.
- Bundle size from bundled TypeScript source:
browser.ts197,173 B raw / 37,198 B gzip ->browser.min.js84,013 B raw / 24,894 B gzip (-113,160 B raw, -12,304 B gzip).
- Added condition-specific root declaration targets so browser-conditioned root imports resolve to browser declarations while Node/default root imports keep server-capable declarations.
- Preserved the root browser runtime condition and documented that server-only APIs remain on the Node/server entrypoints.
- Added packed-artifact export-map, declaration/runtime parity, and static
import checks for root browser, root Node, explicit
/browser, and explicit/serverentrypoints. - Added component-scoped continuous intersection helpers with
this.intersect(...)andthis.on("intersect", options?, fn), preservingon:visibleas a one-shot visibility lifecycle hook. - Added declarative
on:intersectwithintersect:threshold,intersect:root-margin, andintersect:oncepseudo-event options, including customintersectattribute prefix support. - Added observer cleanup coverage for component teardown, boundary swaps, fallback scheduling, repeated entries, and existing visible compatibility.
- Moved root release artifacts to an ignored generated-output workflow: tests, bundle checks, pack checks, and generated CI tasks materialize the current package surface before verification or publish.
- Bundle size from bundled TypeScript source:
browser.ts197,173 B raw / 37,198 B gzip ->browser.min.js84,013 B raw / 24,894 B gzip (-113,160 B raw, -12,304 B gzip).
- Validated server proxy arguments, default input payloads, and selected signal values against an explicit JSON transport model before requests leave the caller.
- Rejected values that
JSON.stringifywould silently corrupt, includingundefined, non-finite numbers, functions, symbols, sparse arrays, circular structures, class instances, dates, maps, sets, buffers, streams, and web platform request/body objects. - Added path-aware regression coverage for invalid transport values and documented the supported server-call JSON model.
- Bundle size from bundled TypeScript source:
browser.ts187,564 B raw / 35,332 B gzip ->browser.min.js80,009 B raw / 23,677 B gzip (-107,555 B raw, -11,655 B gzip).
- Deferred boundary receiver sequence commits until patch effects complete so failed DOM swaps, scheduler flushes, redirects, or missing capabilities no longer make the same streamed sequence stale.
- Serialized same-boundary patch application to keep concurrent patches from committing out of order while preserving stale rejection after successful commits.
- Added regression coverage for retryable DOM, scheduler, redirect, and capability failures plus idempotent partial-effect replay.
- Bundle size from bundled TypeScript source:
browser.ts186,064 B raw / 35,039 B gzip ->browser.min.js79,042 B raw / 23,445 B gzip (-107,022 B raw, -11,594 B gzip).
- Serialized rejected async-signal snapshot errors to stable
name,message, andcoderecords so JSON SSR snapshots preserve documented$error.messagebindings during browser activation. - Normalized non-Error rejections into readable error records while omitting arbitrary error object properties from snapshots by default.
- Added regression coverage for JSON snapshot round-trips, error code preservation, non-Error rejection normalization, and SSR activation bindings.
- Bundle size from bundled TypeScript source:
browser.ts185,440 B raw / 34,884 B gzip ->browser.min.js78,754 B raw / 23,362 B gzip (-106,686 B raw, -11,522 B gzip).
- Routed automatic microtask scheduler flush failures through an explicit error channel so failed jobs no longer surface as unhandled promise rejections.
- Reported automatic flush failures to configured
onErrorhandlers orglobalThis.reportError, with scheduler metadata for phase, scope, and key, while preserving manualscheduler.flush()rejection behavior. - Added regression coverage for automatic
onErrorreporting,reportErrordelivery without unhandled rejections, and manual flush rejection metadata. - Bundle size from bundled TypeScript source:
browser.ts184,238 B raw / 34,642 B gzip ->browser.min.js78,267 B raw / 23,232 B gzip (-105,971 B raw, -11,410 B gzip).
- Normalized scheduler batch thenables with
Promise.resolve(value)before attaching cleanup, so PromiseLike values that implement.then()without.finally()are accepted. - Preserved batch-depth restoration, post-batch flushing, and manual rejection propagation for fulfilled, rejected, and native Promise batch work.
- Added scheduler regression coverage for thenables without
.finally(), rejected thenable batches, and Promise rejection propagation. - Bundle size from bundled TypeScript source:
browser.ts183,444 B raw / 34,419 B gzip ->browser.min.js77,949 B raw / 23,138 B gzip (-105,495 B raw, -11,281 B gzip).
- Scoped server-result application tracking to each framework invocation so the same envelope object can apply effects again for separate calls without double-applying inside one nested server call chain.
- Stopped mutating caller-owned server-result objects to record application state, including extensible, sealed, frozen, redirect, and error envelopes.
- Added regression coverage for repeated shared-envelope invocations, frozen/sealed envelopes, original server errors, repeatable redirects, and unchanged result-object own keys.
- Bundle size from bundled TypeScript source:
browser.ts183,427 B raw / 34,417 B gzip ->browser.min.js77,932 B raw / 23,134 B gzip (-105,495 B raw, -11,283 B gzip).
- Introduced an explicit
__async_server_result__: 1marker for framework server-result envelopes so ordinary domain objects with fields such asvalue,signals,cache,html,boundary,redirect, orerrorremain application values. - Centralized server-result effect application and unwrapping across local
registry, remote proxy, and handler command paths so
.run(...)and namespaced calls return equivalent values without double-applying effects. - Kept cache-only and other effect-only server envelopes representable through the explicit marker and updated server-call, router, partial, and SSR examples to use the protocol.
- Bundle size from bundled TypeScript source:
browser.ts183,176 B raw / 34,360 B gzip ->browser.min.js77,854 B raw / 23,100 B gzip (-105,322 B raw, -11,260 B gzip).
- Owned async-signal runs with private execution tokens so canceled, restored, disposed, unregistered, or superseded work cannot commit late values, errors, or subscriber notifications.
- Captured per-run
this.abortandthis.servercontext so older async work cannot observe or cancel a newer run's abort signal after anawait. - Settled cancellation state immediately for non-cooperative loaders and canceled queued initial async scheduler work during disposal.
- Bundle size from bundled TypeScript source:
browser.ts183,459 B raw / 34,391 B gzip ->browser.min.js77,987 B raw / 23,148 B gzip (-105,472 B raw, -11,243 B gzip).
- Treated materialized signals and lazy async-signal descriptors as one logical namespace so duplicate IDs are rejected consistently.
- Fixed lazy async-signal
unregister(...)before and after materialization so removed descriptors cannot rematerialize. - Preserved reusable app async-signal declarations when materialized runtime async state is destroyed.
- Bundle size from bundled TypeScript source:
browser.ts181,266 B raw / 33,853 B gzip ->browser.min.js77,285 B raw / 22,868 B gzip (-103,981 B raw, -10,985 B gzip).
- Restored snapshot signal keys as exact IDs so dotted plain, async, and
component-scoped signal IDs such as
product.loadsurvive SSR activation without becoming nested properties under their first segment. - Adopted async-signal descriptors before restoring matching snapshot state so
dotted async signals preserve
$value,$status, and$versionwithout an immediate client refresh. - Kept server-result signal patches on nested first-segment path semantics for
updates such as
product.title. - Bundle size from bundled TypeScript source:
browser.ts180,585 B raw / 33,742 B gzip ->browser.min.js76,946 B raw / 22,793 B gzip (-103,639 B raw, -10,949 B gzip).
- Isolated runtime-owned signal, async-signal, scheduler, request, and cache
state so each
createApp(...)call materializes fresh mutable state from reusable app declarations. - Preserved reusable app declarations across runtime destroy/recreate cycles,
late
app.use(...)adoption, server render repetition, and peer async-signal subscribers. - Added direct runtime-isolation regression coverage and regenerated the published browser/server artifacts.
- Bundle size from bundled TypeScript source:
browser.ts179,469 B raw / 33,612 B gzip ->browser.min.js76,458 B raw / 22,690 B gzip (-103,011 B raw, -10,922 B gzip).
- Published the post-
0.11.1feedback-regression hardening now onmain, including scheduler scope revival, server error envelopes, async-signal SSR snapshot restore, lazy component error handling, router prefetch context, server proxy transport validation, and package export smoke coverage. - Refreshed the generated Async Pipeline workflow and lock metadata to
@async/pipeline0.9.1. - Ignored local
docs/goals/GoalBuddy planning bundles.
- Removed the literal old global fetch identifier from published release notes so package-wide text scans stay focused on runtime artifacts.
- Hardened scheduler scope revival, server error envelopes, async-signal SSR snapshot restore, lazy component sync-rendering errors, router prefetch context, server proxy transport validation, and package export smoke tests.
- Bundle size from bundled TypeScript source:
browser.ts177,243 B raw / 33,354 B gzip ->browser.min.js75,517 B raw / 22,516 B gzip (-101,726 B raw, -10,838 B gzip).
- Removed the networked
ssr-sparouter mode and route-fragment fetching sossractivates server-rendered HTML and snapshots without client route fetches. - Changed browser navigation to render registered SPA partials locally in
spaandcsrmodes while leaving same-origin document navigation alone inssrandmpamodes. - Replaced the server proxy's implicit global fetch default with an
explicit
transportcallback supplied by application code. - Published only generated runtime artifacts and declarations:
browser.*,server.js,framework.ts, andframework.d.ts; source, tests, and examples are no longer included in the package tarball. - Added regression coverage for SSR snapshot activation without fetch, SPA stale/error navigation behavior, explicit server proxy transports, and static generated-bundle scans for implicit global fetch access.
- Bundle size from bundled TypeScript source:
browser.ts171,908 B raw / 32,421 B gzip ->browser.min.js72,827 B raw / 21,845 B gzip (-99,081 B raw, -10,576 B gzip).
- Fixed intercepted router link, form, and popstate navigation failures so they update router error state and do not create unhandled promise rejections.
- Preserved native same-document hash link behavior and made malformed encoded dynamic route params fall back to the raw segment instead of throwing.
- Hardened rootless detach cleanup, lazy descriptor import retry, server JSON
transport validation, and
cache.getOrSet(...)handling for cachedundefinedvalues. - Expanded regression coverage for scheduler reentrancy, boundary receiver patch shapes, root lifecycle, lazy descriptors, server transport edge cases, component lifecycle ordering, and installed package export-map shape.
- Bundle size from bundled TypeScript source:
browser.ts173,774 B raw / 32,727 B gzip ->browser.min.js73,680 B raw / 22,047 B gzip (-100,094 B raw, -10,680 B gzip).
- Added Terser-powered browser bundle minification and pointed legacy
module/browseranalyzer fields plus the rootexports.browsercondition atbrowser.min.js. - Bundle size from bundled TypeScript source:
browser.ts171,471 B raw / 32,301 B gzip ->browser.min.js72,753 B raw / 21,763 B gzip (-98,718 B raw, -10,538 B gzip).
- Added rootless browser startup plus
attachRoot,detachRoot,inspectRoots, and streamedapplySnapshot(...)support for advanced build-step bootstrapping. - Added compact lazy registry descriptors with
_asyncasset resolution, inferred exports, and lazy handler, partial, component, and async-signal materialization. - Added optional
async-containerandasync-suspensecustom elements while preserving the existingasync:container,async:boundary, andthis.suspense(...)Layer 1 APIs.
- Added
createBoundaryReceiver(...)for optional out-of-order boundary patch delivery with per-boundary sequence checks, signal/cache effect ordering, scheduler flushing, redirects, and destroyed parent-scope filtering.
- Split browser and server entrypoints with
@async/framework/browser,@async/framework/server, browser-only CDN bundles, and server-only local function registry exports. - Added
createRequestContextStore(...)for Node request-scoped server function context usingAsyncLocalStorage. - Added the Layer 1.5 scheduler for deterministic signal binding, lifecycle, effect, async, and post-flush phases.
- Added browser microtask scheduling by default and manual scheduler flushing for server render paths.
- Threaded
this.schedulerthrough loader, handler, component, async signal, server, router, and partial contexts.
- Added router navigation abort/version guards so stale route partials cannot
clobber newer navigations, and route partial contexts receive
this.abort. - Added ranked route matching so static and dynamic routes win over wildcard fallbacks regardless of registration order.
- Added
readSnapshot(...)and automatic browser activation from SSR snapshot scripts. - Fixed repeated server result application when proxy/server envelopes pass through namespace or handler callers.
- Added in-flight
cache.getOrSet(...)deduplication and clear proxy errors forFile,Blob, andFormDatavalues that the JSON transport cannot send. - Changed
framework.tsfrom a source facade to a bundled TypeScript source entrypoint.
- Added
Loaderas the canonical public loader factory, includingAsync.Loader(...)for UMD script-tag usage, while keepingAsyncLoaderas a compatibility alias. - Added generated root CDN artifacts:
framework.min.js,framework.umd.js,framework.umd.min.js,framework.ts, andframework.d.ts. - Added package exports and docs for ESM, compact ESM, UMD, compact UMD, and TypeScript source/types entrypoints.
- Added exported helpers to the UMD-only
globalThis.Asyncobject for script-tag CDN usage while keeping ESMAsyncas the app hub export. - Added UMD namespace conflict checks so generated helpers cannot silently
overwrite app-hub fields such as
use,start, orregistry. - Added
registry:lint, a cached package linter that emits a local registry manifest and detects conflicting signal, handler, server, partial, route, or component declarations while skipping generated root bundles.
- Added
this.suspense(signalRef, views)for component-owned async boundary templates without adding a wrapper, rerender loop, hydration, or promise throwing. - Added
signal:prop:*property bindings and tests for inline signal refs insignal:text,signal:attr:*, andsignal:prop:*. - Added explicit
unregister(id)APIs to runtime registries and component cleanup for scoped signals, async signals, computed signals, and handlers. - Added boundary swap cleanup for mounted component fragments and old DOM bindings.
- Added server-call normalization for async signals, including returned signal effects, proxy abort propagation, and stable server error messages.
- Added
preventas a command-event alias forpreventDefault.
- Added a generated root
framework.jsESM bundle for UNPKG browser imports. - Expanded the README with Async layer definitions and an htmx comparison.
- Added
on:attachas the canonical component attach lifecycle pseudo-event withon:mountkept as a compatibility alias. - Added top-level
class:*bindings, including aggregateclass:string/object/array class sets. - Added inline
htmltemplate bindings for signal refs, class arrays/objects,value="${signalRef}", and generated component handlers viathis.handler(fn). - Added generated component-local signals via
this.signal(initial).
- Added a shared registry store behind
Async, app runtimes, and concrete registries so apps can inspect signals, handlers, server ids, routes, partials, components, and split cache state from one place. - Added configurable HTML attribute prefixes, with
async:*,signal:*, andon:*as the defaults plus explicit support fordata-async-*,data-signal-*, anddata-on-*. - Declared the UNPKG package entry explicitly so the package root can be used as a no-build browser ESM CDN import.
- Documented the UNPKG import-map setup for importing
@async/frameworkby package name in no-build browser apps.
- Fixed release doctor validation to accept the pipeline-generated GitHub Release description wrapper around changelog entries.
- Fixed the generated release pipeline for the no-build package by verifying npm and GitHub Release parity without requiring a GitHub Packages mirror.
- Added
csrrouter mode for client-side first route rendering plus local SPA navigation through route partial boundary swaps.
- Reset
@async/frameworkto Layer 1 AsyncLoader. - Added signals, async signals, delegated handlers, component fragment helpers, and out-of-order boundary swaps.
- Added Layer 2 command events, server calls, route partials, and client router primitives.
- Added
Async.use(...), app runtimes,createSignal,defineRoute,defineComponent, split browser/server cache registries, and SSR render activation helpers. - Added no-build static examples and Node test coverage.
- Added generated
@async/pipelineverification, GitHub Pages, and release workflow support.