fix(sse): harden sse directive — loop guard, limit validation, terminal untrack, dead code#293
fix(sse): harden sse directive — loop guard, limit validation, terminal untrack, dead code#293ErickXavier wants to merge 3 commits into
Conversation
…rminal untrack, dead code removal 1. Add _isLoopElement() guard matching http.js pattern — warn and bail when sse is placed on a loop element. 2. Use hasAttribute() instead of truthiness to detect sse-limit presence. Empty string / zero / negative values now correctly warn and trigger the unbounded-memory growth warning for append/prepend modes. 3. Terminal server close (readyState CLOSED) now removes the dead EventSource from per-origin connection tracking, preventing false- positive 6-connection warnings. 4. Remove unreachable try/catch around _execStatement call — the function handles all errors internally and never rethrows.
QA T7 Gate — Verdict: CHANGES_REQUESTEDFull review of the 4 sse.js fixes, run in an isolated worktree at origin/fix/NOJS-285 (a31b58b). BlockersB1 — Loop guard is bypassed by loop clones ( B2 — Should-fix (non-blocking)
Nits
Verified sound
Re-request review after B1 and the B2 decision land. |
…loops Loop clones were not stripping the `sse` attribute, causing each clone to open its own EventSource when the loop list was populated. The template-level _isLoopElement guard only fires on the original element (empty-list case). Add "sse" to _LOOP_ATTRS (mirrors the HTTP verb pattern) so clones never re-fire the SSE directive. Two regression tests cover the populated-list path for both `each` and `foreach` variants.
QA T7 Re-Gate — Verdict: APPROVEDFocused delta re-review of B1 (loop clones each opening an EventSource) — FIXED, verified
B2 (docs
|
Add `query` to `_LOOP_ATTRS` — it was the only HTTP verb in `HTTP_METHODS` guarded by `_isLoopElement` but missing from the strip list, causing one fetch per clone on populated loops. Systematic audit confirmed no other directives are missing: - HTTP verbs (get/post/put/patch/delete): already present - query: ADDED (was missing — the bug) - sse: already present (98cd415) - page-title/page-description/page-canonical/page-jsonld: already present - computed/watch: guarded but intentionally excluded (no per-element side effect; clones need their own derived state) - else-if/else: already handled (else-if in list, else via stripElse param) Regression tests: 3 new tests in loop-hygiene.test.js verify query on populated loops fires zero fetches and the attribute is stripped from clones. Revert-to-red confirmed for the attr-strip test.
Summary
Fixes five issues in
src/directives/sse.js(NOJS-285, T2 of EPIC NOJS-283):Loop element guard — SSE on a
foreach/each/forelement now warns and bails, matching the existing pattern inhttp.jsvia the shared_isLoopElement()helper fromloops.js.sse-limit=""validation — Empty string, zero, and negative values were silently accepted due to a truthiness check ongetAttribute(). Now useshasAttribute()soparseInt("", 10) → NaNcorrectly triggers the validity warning. The unbounded-memory-growth warning also fires as expected.Terminal close untrack — When the server closes the connection (readyState CLOSED), the dead
EventSourceis now removed from the per-origin connection tracking map. Previously it stayed, causing false-positive 6-connection warnings.Dead code removal — The
try/catcharound_execStatement()in theonMessagehandler was unreachable —_execStatementcatches all errors internally and never rethrows. Removed the redundant wrapper.Bundle delta — Net +16 bytes gzip (44010 vs 43994 baseline). New guard/validation code offset by dead-code removal. No readability sacrificed.
Test evidence
npx jest --no-coverage __tests__/sse.test.js— 50 tests pass (7 new: 4 loop guard, 2 limit validation, 1 terminal untrack)npm test— 2201/2201 pass (full suite green)sse.js: 100% statements, 100% functions, 100% lines, 92.38% branchesnode build.js— clean build,dist/committedTest plan