HS test generator: fix toHaveCSS, locals, and \"-escapes — +28 tests

Generator changes (tests/playwright/generate-sx-tests.py):
- toHaveCSS regex: balance parens so `'rgb(255, 0, 0)'` is captured intact
  (was truncating at first `)`)
- Map browser-computed colors `rgb(R,G,B)` back to CSS keywords
  (red/green/blue/black/white) — our DOM mock returns the inline value
- js_val_to_sx now handles object literals `{a: 1, b: {c: 2}}` → `{:a 1 :b {:c 2}}`
- Pattern 2 (`var x = await run(...)`) now captures locals via balanced-brace
  scan and emits `eval-hs-locals` instead of `eval-hs`
- Pattern 1 with locals: emit `eval-hs-locals` (was wrapping in `let`, which
  doesn't reach the inner HS env)
- Stop collapsing `\"` → `"` in raw HTML (line 218): the backslash escapes
  are legitimate in single-quoted `_='...'` HS attribute values containing
  nested HS scripts

Test-framework changes (regenerated into spec/tests/test-hyperscript-behavioral.sx):
- `_hs-wrap-body`: returns expression value if non-nil, else `it`. Lets bare
  expressions (`foo.foo`) and `it`-mutating scripts (`pick first 3 of arr;
  set $test to it`) both round-trip through the same wrapper
- `eval-hs-locals` now injects locals via `(let ((name (quote val)) ...) sx)`
  rather than `apply handler (cons nil vals)` — works around a JIT loop on
  some compiled forms (e.g. `bar.doh of foo` with undefined `bar`)

Also synced lib/hyperscript/*.sx → shared/static/wasm/sx/hs-*.sx (the WASM
test runner reads from the wasm/sx/ copies).

Net per-cluster pass counts (vs prior baseline):
- put: 23 → 29 (+6)
- set: 21 → 28 (+7)
- show: 7 → 15 (+8)
- expressions/propertyAccess: 3 → 9 (+6)
- expressions/possessiveExpression: 17 → 18 (+1)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 09:18:21 +00:00
parent 0515295317
commit a11d0941e9
7 changed files with 451 additions and 194 deletions

View File

@@ -53,13 +53,20 @@
((sx (hs-to-sx-from-source src)))
(let
((extra-vars (hs-collect-vars sx)))
(let
((bindings (append (list (list (quote it) nil) (list (quote event) nil)) (map (fn (v) (list v nil)) extra-vars))))
(eval-expr-cek
(list
(quote fn)
(list (quote me))
(list (quote let) bindings sx)))))))))
(do
(for-each
(fn (v) (eval-expr-cek (list (quote define) v nil)))
extra-vars)
(let
((guarded (list (quote guard) (list (quote _e) (list (quote true) (list (quote if) (list (quote and) (list (quote list?) (quote _e)) (list (quote =) (list (quote first) (quote _e)) "hs-return")) (list (quote nth) (quote _e) 1) (list (quote raise) (quote _e))))) sx)))
(eval-expr-cek
(list
(quote fn)
(list (quote me))
(list
(quote let)
(list (list (quote it) nil) (list (quote event) nil))
guarded))))))))))
;; ── Activate a single element ───────────────────────────────────
;; Reads the _="..." attribute, compiles, and executes with me=element.
@@ -70,9 +77,10 @@
(fn
(el)
(let
((src (dom-get-attr el "_")))
((src (dom-get-attr el "_")) (prev (dom-get-data el "hs-script")))
(when
(and src (not (dom-get-data el "hs-active")))
(and src (not (= src prev)))
(dom-set-data el "hs-script" src)
(dom-set-data el "hs-active" true)
(let ((handler (hs-handler src))) (handler el))))))
@@ -80,6 +88,21 @@
;; Called once at page load. Finds all elements with _ attribute,
;; compiles their hyperscript, and activates them.
(define
hs-deactivate!
(fn
(el)
(let
((unlisteners (or (dom-get-data el "hs-unlisteners") (list))))
(for-each (fn (u) (when u (u))) unlisteners)
(dom-set-data el "hs-unlisteners" (list))
(dom-set-data el "hs-active" false)
(dom-set-data el "hs-script" nil))))
;; ── Boot subtree: for dynamic content ───────────────────────────
;; Called after HTMX swaps or dynamic DOM insertion.
;; Only activates elements within the given root.
(define
hs-boot!
(fn
@@ -88,10 +111,6 @@
((elements (dom-query-all (host-get (host-global "document") "body") "[_]")))
(for-each (fn (el) (hs-activate! el)) elements))))
;; ── Boot subtree: for dynamic content ───────────────────────────
;; Called after HTMX swaps or dynamic DOM insertion.
;; Only activates elements within the given root.
(define
hs-boot-subtree!
(fn