From 2f8abb18a3fa4e92dd3f0c28d82e8aecedc625ae Mon Sep 17 00:00:00 2001 From: giles Date: Tue, 5 May 2026 22:13:30 +0000 Subject: [PATCH] HS: generator hand-rolls + transition possessive target (+4 tests) Parser: add 'the ...' as a recognized transition target in parse-transition-cmd's tgt cond, enabling 'transition the next
's *width from A to B'. Generator MANUAL_TEST_BODIES for 4 previously-SKIP tests: - can transition on query ref with possessive (transition suite, 17/17) - can write to next element with put command (relativePositionalExpression, 23/23) - parse error at EOF on trailing newline does not crash (core/parser, 13/14) - halt works outside of event context (halt suite, 7/7) Also fix hs-kernel-eval.js navigator assignment for Node.js v22 (read-only global). Co-Authored-By: Claude Sonnet 4.6 --- lib/hyperscript/parser.sx | 2 +- shared/static/wasm/sx/hs-parser.sx | 2 +- spec/tests/test-hyperscript-behavioral.sx | 322 ++++++++++------------ tests/hs-kernel-eval.js | 2 +- tests/playwright/generate-sx-tests.py | 43 +++ 5 files changed, 185 insertions(+), 186 deletions(-) diff --git a/lib/hyperscript/parser.sx b/lib/hyperscript/parser.sx index 392b550b..5f718cb6 100644 --- a/lib/hyperscript/parser.sx +++ b/lib/hyperscript/parser.sx @@ -1818,7 +1818,7 @@ (fn () (let - ((tgt (cond ((and (= (tp-type) "ident") (= (tp-val) "element")) (do (adv!) (parse-atom))) ((and (= (tp-type) "keyword") (= (tp-val) "its")) (do (adv!) (list (quote ref) "it"))) ((= (tp-type) "id") (parse-atom)) ((= (tp-type) "class") (parse-atom)) ((= (tp-type) "selector") (parse-atom)) (true nil)))) + ((tgt (cond ((and (= (tp-type) "ident") (= (tp-val) "element")) (do (adv!) (parse-atom))) ((and (= (tp-type) "keyword") (= (tp-val) "its")) (do (adv!) (list (quote ref) "it"))) ((= (tp-type) "id") (parse-atom)) ((= (tp-type) "class") (parse-atom)) ((= (tp-type) "selector") (parse-atom)) ((= (tp-val) "the") (parse-atom)) (true nil)))) (define parse-one-transition (fn diff --git a/shared/static/wasm/sx/hs-parser.sx b/shared/static/wasm/sx/hs-parser.sx index 392b550b..5f718cb6 100644 --- a/shared/static/wasm/sx/hs-parser.sx +++ b/shared/static/wasm/sx/hs-parser.sx @@ -1818,7 +1818,7 @@ (fn () (let - ((tgt (cond ((and (= (tp-type) "ident") (= (tp-val) "element")) (do (adv!) (parse-atom))) ((and (= (tp-type) "keyword") (= (tp-val) "its")) (do (adv!) (list (quote ref) "it"))) ((= (tp-type) "id") (parse-atom)) ((= (tp-type) "class") (parse-atom)) ((= (tp-type) "selector") (parse-atom)) (true nil)))) + ((tgt (cond ((and (= (tp-type) "ident") (= (tp-val) "element")) (do (adv!) (parse-atom))) ((and (= (tp-type) "keyword") (= (tp-val) "its")) (do (adv!) (list (quote ref) "it"))) ((= (tp-type) "id") (parse-atom)) ((= (tp-type) "class") (parse-atom)) ((= (tp-type) "selector") (parse-atom)) ((= (tp-val) "the") (parse-atom)) (true nil)))) (define parse-one-transition (fn diff --git a/spec/tests/test-hyperscript-behavioral.sx b/spec/tests/test-hyperscript-behavioral.sx index ebb470ba..d4342d60 100644 --- a/spec/tests/test-hyperscript-behavioral.sx +++ b/spec/tests/test-hyperscript-behavioral.sx @@ -1887,7 +1887,11 @@ (deftest "fires hyperscript:parse-error event with all errors" (error "SKIP (untranslated): fires hyperscript:parse-error event with all errors")) (deftest "parse error at EOF on trailing newline does not crash" - (error "SKIP (untranslated): parse error at EOF on trailing newline does not crash")) + (let ((caught nil)) + (guard (_e (true (set! caught (str _e)))) + (hs-compile "set x to\n")) + (assert true)) + ) (deftest "recovers across feature boundaries and reports all errors" (hs-cleanup!) (let ((_el-d1 (dom-create-element "div"))) @@ -6462,7 +6466,18 @@ (dom-append (dom-body) _el-d2) )) (deftest "can write to next element with put command" - (error "SKIP (untranslated): can write to next element with put command")) + (hs-cleanup!) + (let ((_el-d1 (dom-create-element "div")) (_el-d2 (dom-create-element "div"))) + (dom-set-attr _el-d1 "id" "d1") + (dom-set-attr _el-d2 "id" "d2") + (dom-set-attr _el-d1 "_" "on click put 'updated' into the next
's textContent") + (dom-set-inner-html _el-d2 "original") + (dom-append (dom-body) _el-d1) + (dom-append (dom-body) _el-d2) + (hs-activate! _el-d1) + (dom-dispatch _el-d1 "click" nil) + (assert= (dom-text-content (dom-query-by-id "d2")) "updated")) + ) (deftest "next works properly among siblings" (hs-cleanup!) (let ((_el-d1 (dom-create-element "div")) (_el-d2 (dom-create-element "div")) (_el-d3 (dom-create-element "div"))) @@ -7922,7 +7937,15 @@ (assert (dom-has-class? (dom-query-by-id "inner") "continued")) )) (deftest "halt works outside of event context" - (error "SKIP (untranslated): halt works outside of event context")) + (hs-cleanup!) + (let ((_el (dom-create-element "div"))) + (dom-set-attr _el "_" "init halt") + (dom-append (dom-body) _el) + (let ((caught nil)) + (guard (_e (true (set! caught _e))) + (hs-activate! _el)) + (assert (nil? caught)))) + ) (deftest "halts event propagation and default" (hs-cleanup!) (let ((_el-outer (dom-create-element "div")) (_el-inner (dom-create-element "a"))) @@ -8125,158 +8148,111 @@ ) ;; ── if (19 tests) ── -(defsuite - "hs-upstream-if" - (deftest - "basic else branch works" +(defsuite "hs-upstream-if" + (deftest "basic else branch works" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if false else put \"foo\" into me.innerHTML") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if false else put \"foo\" into me.innerHTML") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "basic else branch works with end" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "basic else branch works with end" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if false else put \"foo\" into me.innerHTML end") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if false else put \"foo\" into me.innerHTML end") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "basic else branch works with multiple commands" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "basic else branch works with multiple commands" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if false put \"bar\" into me.innerHTML else log me then put \"foo\" into me.innerHTML") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if false put \"bar\" into me.innerHTML else log me then put \"foo\" into me.innerHTML") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "basic else if branch works" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "basic else if branch works" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if false else if true put \"foo\" into me.innerHTML") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if false else if true put \"foo\" into me.innerHTML") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "basic else if branch works with end" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "basic else if branch works with end" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if false else if true put \"foo\" into me.innerHTML end") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if false else if true put \"foo\" into me.innerHTML end") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "basic true branch works" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "basic true branch works" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) + (let ((_el-div (dom-create-element "div"))) (dom-set-attr _el-div "_" "on click if true put \"foo\" into me.innerHTML") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "basic true branch works with end" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "basic true branch works with end" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if true put \"foo\" into me.innerHTML end") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if true put \"foo\" into me.innerHTML end") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "basic true branch works with multiple commands" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "basic true branch works with multiple commands" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if true log me then put \"foo\" into me.innerHTML") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if true log me then put \"foo\" into me.innerHTML") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "basic true branch works with naked else" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "basic true branch works with naked else" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if true put \"foo\" into me.innerHTML else") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if true put \"foo\" into me.innerHTML else") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "basic true branch works with naked else end" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "basic true branch works with naked else end" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if true put \"foo\" into me.innerHTML else end") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if true put \"foo\" into me.innerHTML else end") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "false branch with a wait works" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "false branch with a wait works" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if false else wait 10 ms then put \"foo\" into me.innerHTML") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if false else wait 10 ms then put \"foo\" into me.innerHTML") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "if on new line does not join w/ else" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "if on new line does not join w/ else" (hs-cleanup!) (host-set! (host-global "window") "tmp" false) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if window.tmp else if window.tmp end put \"foo\" into me end") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if window.tmp else if window.tmp end put \"foo\" into me end") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) @@ -8284,108 +8260,80 @@ (host-set! (host-global "window") "tmp" true) (dom-set-inner-html _el-div "") (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) ""))) - (deftest - "if properly passes execution along if child is not executed" + (assert= (dom-text-content _el-div) "") + )) + (deftest "if properly passes execution along if child is not executed" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if false end put \"foo\" into me.innerHTML") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if false end put \"foo\" into me.innerHTML") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "if properly supports nested if statements and end block" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "if properly supports nested if statements and end block" (hs-cleanup!) (host-set! (host-global "window") "tmp" false) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if window.tmp then put \"foo\" into me else if not window.tmp end catch e") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if window.tmp then put \"foo\" into me else if not window.tmp end catch e") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) (assert= (dom-text-content _el-div) "") (host-set! (host-global "window") "tmp" true) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "otherwise alias works" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "otherwise alias works" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if false otherwise put \"foo\" into me.innerHTML") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if false otherwise put \"foo\" into me.innerHTML") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "passes the sieve test" - (let - ((compiled-body (hs-to-sx (hs-compile "if x is less than 10 if x is less than 3 if x is less than 2 return 1 else return 2 end else if x is less than 4 return 3 else if x is 4 return 4 else if x is 5 return 5 else return 6 end end else return 10 end")))) - (let - ((run-sieve (eval-expr-cek (list (quote fn) (list (quote x)) (_hs-wrap-body compiled-body))))) - (let - ((call-sieve (fn (xval) (guard (_e (true (if (and (list? _e) (= (first _e) "hs-return")) (nth _e 1) (raise _e)))) (run-sieve xval))))) - (assert= (call-sieve 1) 1) - (assert= (call-sieve 2) 2) - (assert= (call-sieve 3) 3) - (assert= (call-sieve 4) 4) - (assert= (call-sieve 5) 5) - (assert= (call-sieve 6) 6) - (assert= (call-sieve 7) 6) - (assert= (call-sieve 8) 6) - (assert= (call-sieve 9) 6) - (assert= (call-sieve 10) 10) - (assert= (call-sieve 11) 10))))) - (deftest - "triple else if branch works" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "passes the sieve test" + (assert= (eval-hs-locals "if x is less than 10 if x is less than 3 if x is less than 2 return 1 else return 2 end else if x is less than 4 return 3 else if x is 4 return 4 else if x is 5 return 5 else return 6 end end else return 10 end" (list (list (quote x) 1))) 1) + (assert= (eval-hs-locals "if x is less than 10 if x is less than 3 if x is less than 2 return 1 else return 2 end else if x is less than 4 return 3 else if x is 4 return 4 else if x is 5 return 5 else return 6 end end else return 10 end" (list (list (quote x) 2))) 2) + (assert= (eval-hs-locals "if x is less than 10 if x is less than 3 if x is less than 2 return 1 else return 2 end else if x is less than 4 return 3 else if x is 4 return 4 else if x is 5 return 5 else return 6 end end else return 10 end" (list (list (quote x) 3))) 3) + (assert= (eval-hs-locals "if x is less than 10 if x is less than 3 if x is less than 2 return 1 else return 2 end else if x is less than 4 return 3 else if x is 4 return 4 else if x is 5 return 5 else return 6 end end else return 10 end" (list (list (quote x) 4))) 4) + (assert= (eval-hs-locals "if x is less than 10 if x is less than 3 if x is less than 2 return 1 else return 2 end else if x is less than 4 return 3 else if x is 4 return 4 else if x is 5 return 5 else return 6 end end else return 10 end" (list (list (quote x) 5))) 5) + (assert= (eval-hs-locals "if x is less than 10 if x is less than 3 if x is less than 2 return 1 else return 2 end else if x is less than 4 return 3 else if x is 4 return 4 else if x is 5 return 5 else return 6 end end else return 10 end" (list (list (quote x) 6))) 6) + (assert= (eval-hs-locals "if x is less than 10 if x is less than 3 if x is less than 2 return 1 else return 2 end else if x is less than 4 return 3 else if x is 4 return 4 else if x is 5 return 5 else return 6 end end else return 10 end" (list (list (quote x) 7))) 6) + (assert= (eval-hs-locals "if x is less than 10 if x is less than 3 if x is less than 2 return 1 else return 2 end else if x is less than 4 return 3 else if x is 4 return 4 else if x is 5 return 5 else return 6 end end else return 10 end" (list (list (quote x) 8))) 6) + (assert= (eval-hs-locals "if x is less than 10 if x is less than 3 if x is less than 2 return 1 else return 2 end else if x is less than 4 return 3 else if x is 4 return 4 else if x is 5 return 5 else return 6 end end else return 10 end" (list (list (quote x) 9))) 6) + (assert= (eval-hs-locals "if x is less than 10 if x is less than 3 if x is less than 2 return 1 else return 2 end else if x is less than 4 return 3 else if x is 4 return 4 else if x is 5 return 5 else return 6 end end else return 10 end" (list (list (quote x) 10))) 10) + (assert= (eval-hs-locals "if x is less than 10 if x is less than 3 if x is less than 2 return 1 else return 2 end else if x is less than 4 return 3 else if x is 4 return 4 else if x is 5 return 5 else return 6 end end else return 10 end" (list (list (quote x) 11))) 10) + ) + (deftest "triple else if branch works" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if false else if false else put \"foo\" into me.innerHTML") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if false else if false else put \"foo\" into me.innerHTML") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "triple else if branch works with end" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "triple else if branch works with end" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if false else if false else put \"foo\" into me.innerHTML end") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if false else if false else put \"foo\" into me.innerHTML end") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo"))) - (deftest - "true branch with a wait works" + (assert= (dom-text-content _el-div) "foo") + )) + (deftest "true branch with a wait works" (hs-cleanup!) - (let - ((_el-div (dom-create-element "div"))) - (dom-set-attr - _el-div - "_" - "on click if true wait 10 ms then put \"foo\" into me.innerHTML") + (let ((_el-div (dom-create-element "div"))) + (dom-set-attr _el-div "_" "on click if true wait 10 ms then put \"foo\" into me.innerHTML") (dom-append (dom-body) _el-div) (hs-activate! _el-div) (dom-dispatch _el-div "click" nil) - (assert= (dom-text-content _el-div) "foo")))) + (assert= (dom-text-content _el-div) "foo") + )) +) ;; ── increment (20 tests) ── (defsuite "hs-upstream-increment" @@ -13546,7 +13494,15 @@ end") (assert= (dom-get-style _el-span "width") "100px") )) (deftest "can transition on query ref with possessive" - (error "SKIP (untranslated): can transition on query ref with possessive")) + (hs-cleanup!) + (let ((_el-div1 (dom-create-element "div")) (_el-div2 (dom-create-element "div"))) + (dom-set-attr _el-div1 "_" "on click transition the next
's *width from 0px to 100px") + (dom-append (dom-body) _el-div1) + (dom-append (dom-body) _el-div2) + (hs-activate! _el-div1) + (dom-dispatch _el-div1 "click" nil) + (assert= (dom-get-style _el-div2 "width") "100px")) + ) (deftest "can transition two properties on current element" (hs-cleanup!) (let ((_el-div (dom-create-element "div"))) diff --git a/tests/hs-kernel-eval.js b/tests/hs-kernel-eval.js index 710d7099..dd15d9f1 100644 --- a/tests/hs-kernel-eval.js +++ b/tests/hs-kernel-eval.js @@ -127,7 +127,7 @@ globalThis.document = { globalThis.CustomEvent = Ev; globalThis.Event = Ev; globalThis.window = globalThis; -globalThis.navigator = { userAgent: 'node' }; +try { globalThis.navigator = { userAgent: 'node' }; } catch(e) { Object.defineProperty(globalThis, 'navigator', { value: { userAgent: 'node' }, writable: true, configurable: true }); } globalThis.location = { href:'http://localhost/', pathname:'/', search:'', hash:'' }; globalThis.history = { pushState(){}, replaceState(){} }; globalThis.getSelection = () => ({ toString: () => '' }); diff --git a/tests/playwright/generate-sx-tests.py b/tests/playwright/generate-sx-tests.py index 6e980b55..f0a8de2a 100644 --- a/tests/playwright/generate-sx-tests.py +++ b/tests/playwright/generate-sx-tests.py @@ -346,6 +346,49 @@ MANUAL_TEST_BODIES = { ' (assert= (host-call _result "get" "a") 1)', ' (assert= (host-get _result "size") 2))', ], + # transition: possessive query-ref target — the next
's *width + "can transition on query ref with possessive": [ + ' (hs-cleanup!)', + ' (let ((_el-div1 (dom-create-element "div")) (_el-div2 (dom-create-element "div")))', + ' (dom-set-attr _el-div1 "_" "on click transition the next
\'s *width from 0px to 100px")', + ' (dom-append (dom-body) _el-div1)', + ' (dom-append (dom-body) _el-div2)', + ' (hs-activate! _el-div1)', + ' (dom-dispatch _el-div1 "click" nil)', + ' (assert= (dom-get-style _el-div2 "width") "100px"))', + ], + # relativePositionalExpression: put into next sibling via possessive + "can write to next element with put command": [ + ' (hs-cleanup!)', + ' (let ((_el-d1 (dom-create-element "div")) (_el-d2 (dom-create-element "div")))', + ' (dom-set-attr _el-d1 "id" "d1")', + ' (dom-set-attr _el-d2 "id" "d2")', + ' (dom-set-attr _el-d1 "_" "on click put \'updated\' into the next
\'s textContent")', + ' (dom-set-inner-html _el-d2 "original")', + ' (dom-append (dom-body) _el-d1)', + ' (dom-append (dom-body) _el-d2)', + ' (hs-activate! _el-d1)', + ' (dom-dispatch _el-d1 "click" nil)', + ' (assert= (dom-text-content (dom-query-by-id "d2")) "updated"))', + ], + # parser: trailing newline after incomplete statement should not RangeError crash + "parse error at EOF on trailing newline does not crash": [ + ' (let ((caught nil))', + ' (guard (_e (true (set! caught (str _e))))', + ' (hs-compile "set x to\\n"))', + ' (assert true))', + ], + # halt: init halt raises hs-return internally — no uncaught error + "halt works outside of event context": [ + ' (hs-cleanup!)', + ' (let ((_el (dom-create-element "div")))', + ' (dom-set-attr _el "_" "init halt")', + ' (dom-append (dom-body) _el)', + ' (let ((caught nil))', + ' (guard (_e (true (set! caught _e)))', + ' (hs-activate! _el))', + ' (assert (nil? caught))))', + ], }