mara on #453: address argus's two yellow nits.
bfcache restore gap
previously openStream registered a pagehide unsubscribe but never
re-subscribed on pageshow, so a bfcache restore left the consumer's
onmessage bound but no events flowing.
fix: maintain a registry of live subscriptions (Map<url, target,
route>). bind page lifecycle hooks once:
- pagehide: unsubscribe every URL, drop route listeners, invalidate
the cached SharedWorker port (it may be collected if all other
tabs closed while this page was frozen).
- pageshow { persisted: true }: get a fresh port via getSharedPort
(creates a new SharedWorker if needed), re-attach every route
listener, re-subscribe to every URL. target.readyState resets to
CONNECTING so the worker's synthetic open after subscribe fires
the consumer's onStreamOpen and triggers a refresh.
worker bundle format
stream-worker.js was bundled as format: 'esm' but loaded as
classic via new SharedWorker(url, name). today's worker has no
imports/exports so the ESM bundle is syntactically valid as a
classic script; argus's concern was that a future contributor
adding an import would silently break things.
fix: switched build.mjs to format: 'iife'. esbuild now wraps the
worker output in (() => { ... })(); any future import statement
would surface as a build error rather than ship broken code.
verified output starts with the IIFE wrapper.
other
- target.close() now reads _sharedPort lazily so close-after-bfcache
(port may have been recreated) doesn't try to postMessage on a
stale reference.
- _activeSubs.delete on close keeps the registry honest if a
consumer ever explicitly closes a stream (none do today, but the
shape stays correct).
validation: npm run build clean. stream-worker.js: 1.8 kb → 1.9 kb
(IIFE wrapper). common.js bfcache logic adds ~30 LOC inside the
existing module — bundle deltas negligible.