`shutdown()` set `accepting = false` and `start()` refused for ever after, so
a queue was single-use. Any process that boots more than one app broke: a test
suite closing one harness and opening the next, a hot reload, a multi-tenant
host. The failure landed far from its cause -- the SECOND app to boot threw
WRN-QUEUE-CLOSED out of the dev server because an unrelated one had shut down
earlier in the same process. That is what turned six example-app security
tests red only when run alongside the rest of the suite.
Starting is an explicit intent to run, so it reopens the queue. `add()` keeps
its guard, so work offered to a queue that is shutting down is still refused.
Also migrates the example app's welcome-email queue to `defineQueue`, which
the new loader requires. It still used `defineJob`, so the loader refused it
and took the whole example app down -- 14 failures from one unmigrated file.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Six fixes, all found by driving a real application rather than by the suite:
- syntax: a quote or brace inside a regex literal unbalanced the brace scanner
- syntax: block comments between members failed to parse, while the same
comment inside a braced body was fine
- compiler: pages never emitted `data-wrn-loop-locals`, so a loop variable in
a handler threw ReferenceError at click time with a green build
- csr: client-rendered `data-for` items never carried the marker either, so a
component's output binding silently dropped every call while a plain DOM
handler in the same position worked
- db: the query generator baked the checkout's line endings into generated
SQL literals, so every build dirtied the working tree
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three things the gate caught that the test suite could not.
The runtime size budget: writing `data-wrn-loop-locals` on client-rendered
loop items pushed reactive-runtime.ts to 51,603 against a 51,400 budget that
had only 125 bytes of headroom. Trimmed the encoder to the
btoa/encodeURIComponent idiom, recovering 65 bytes and leaving the smallest
form that still handles non-ASCII, then raised the budget to 51,600 with the
reason recorded in the file's own convention -- the remaining 263 bytes buy a
correctness fix, not a feature.
The VS Code extension bundles its own copy of the compiler, so the syntax and
compiler fixes made it stale. Rebuilt.
And a bug in the new test: `\{` inside a template literal is an unnecessary
escape, so the "brace inside a regex" case was testing an unescaped brace.
`\{` tests the case it was written for.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A client `data-for` passed its loop locals to hydration in memory but never
wrote the `data-wrn-loop-locals` attribute the SSR path writes. Anything that
resolves locals by READING the DOM -- notably a component's `data-wrn-out-*`
output binding, which calls `decodeLoopLocals(componentRoot)` -- therefore
found nothing and silently dropped the call, with no console error.
A plain DOM handler kept working, because it receives locals through the
hydration closure instead, which is what made the failure look arbitrary: the
same loop variable resolved for `@click` and vanished for a component output.
Both loop paths write the marker now, keyed and non-keyed, so the DOM is the
single source of truth. Encoding goes through UTF-8 before base64 as the
server's does; `btoa` on a raw string throws above U+00FF, which would take the
whole loop down for an ordinary non-ASCII label.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The existing tests assert the marker is emitted. This one executes the
generated module and asserts the rendered HTML carries each item's real,
decodable values -- generated text that reads correctly can still render
wrong, and what matters is what the runtime finds in the DOM at click time.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>