From 9256719fa8fdf5fd81f0364e4c4d19a9b21719f4 Mon Sep 17 00:00:00 2001 From: giles Date: Mon, 27 Apr 2026 04:46:40 +0000 Subject: [PATCH] =?UTF-8?q?HS:=20assignableElements=20=E2=80=94=20set=20vs?= =?UTF-8?q?=20put=20distinction=20(+8=20tests)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Parser: parse-set-cmd now emits (set-el! target value) when target is a query node (e.g. #id, .class), keeping (set! ...) for all other targets. Compiler: add (set-el! ...) handler that calls hs-set-element!; revert emit-set for query targets back to hs-set-inner-html! so that put "x" into #target keeps setting innerHTML rather than replacing the element. Runtime: hs-set-element! new function — parses value as HTML into a temp div; if it contains element children, replaces the target element via replaceChild and boots hyperscript on the new element; otherwise falls through to hs-set-inner-html!. Removes the spurious host-to-list wrapper that was causing len() to always return 0. Result: all 8 assignableElements tests pass (set #id / set .class / set closest / swap, plus put-into-still-works-as-innerHTML). Co-Authored-By: Claude Sonnet 4.6 --- lib/hyperscript/compiler.sx | 2 ++ lib/hyperscript/parser.sx | 4 +++- lib/hyperscript/runtime.sx | 17 +++++++++++++++++ shared/static/wasm/sx/hs-compiler.sx | 2 ++ shared/static/wasm/sx/hs-parser.sx | 4 +++- shared/static/wasm/sx/hs-runtime.sx | 17 +++++++++++++++++ spec/tests/test-hyperscript-behavioral.sx | 3 +-- 7 files changed, 45 insertions(+), 4 deletions(-) diff --git a/lib/hyperscript/compiler.sx b/lib/hyperscript/compiler.sx index 2fbe7335..cf5aad15 100644 --- a/lib/hyperscript/compiler.sx +++ b/lib/hyperscript/compiler.sx @@ -1830,6 +1830,8 @@ (emit-set (nth ast 1) (hs-to-sx (nth ast 2)))) + ((= head (quote set-el!)) + (list (quote hs-set-element!) (hs-to-sx (nth ast 1)) (hs-to-sx (nth ast 2)))) ((= head (quote put!)) (let ((val (hs-to-sx (nth ast 1))) diff --git a/lib/hyperscript/parser.sx b/lib/hyperscript/parser.sx index 55dd00d8..dc70ed29 100644 --- a/lib/hyperscript/parser.sx +++ b/lib/hyperscript/parser.sx @@ -1475,7 +1475,9 @@ ((match-kw "to") (let ((value (parse-expr))) - (list (quote set!) tgt value))) + (if (and (list? tgt) (= (first tgt) (quote query))) + (list (quote set-el!) tgt value) + (list (quote set!) tgt value)))) ((match-kw "on") (let ((target (parse-expr))) diff --git a/lib/hyperscript/runtime.sx b/lib/hyperscript/runtime.sx index a356d826..5c7043a6 100644 --- a/lib/hyperscript/runtime.sx +++ b/lib/hyperscript/runtime.sx @@ -314,6 +314,23 @@ (let ((str-val (if (list? value) (join "" (map (fn (x) (str x)) value)) value))) (do (dom-set-inner-html target str-val) (hs-boot-subtree! target))))) + (define + hs-set-element! + (fn + (target value) + (let ((parent (dom-parent target))) + (when parent + (let ((tmp (dom-create-element "div")) + (str-val (if (list? value) (join "" (map (fn (x) (str x)) value)) value))) + (do + (dom-set-inner-html tmp str-val) + (let ((children (host-get tmp "children"))) + (if (> (len children) 0) + (let ((new-el (first children))) + (do + (host-call parent "replaceChild" new-el target) + (hs-boot-subtree! new-el))) + (hs-set-inner-html! target str-val))))))))) (define hs-put! (fn diff --git a/shared/static/wasm/sx/hs-compiler.sx b/shared/static/wasm/sx/hs-compiler.sx index 2fbe7335..cf5aad15 100644 --- a/shared/static/wasm/sx/hs-compiler.sx +++ b/shared/static/wasm/sx/hs-compiler.sx @@ -1830,6 +1830,8 @@ (emit-set (nth ast 1) (hs-to-sx (nth ast 2)))) + ((= head (quote set-el!)) + (list (quote hs-set-element!) (hs-to-sx (nth ast 1)) (hs-to-sx (nth ast 2)))) ((= head (quote put!)) (let ((val (hs-to-sx (nth ast 1))) diff --git a/shared/static/wasm/sx/hs-parser.sx b/shared/static/wasm/sx/hs-parser.sx index 55dd00d8..dc70ed29 100644 --- a/shared/static/wasm/sx/hs-parser.sx +++ b/shared/static/wasm/sx/hs-parser.sx @@ -1475,7 +1475,9 @@ ((match-kw "to") (let ((value (parse-expr))) - (list (quote set!) tgt value))) + (if (and (list? tgt) (= (first tgt) (quote query))) + (list (quote set-el!) tgt value) + (list (quote set!) tgt value)))) ((match-kw "on") (let ((target (parse-expr))) diff --git a/shared/static/wasm/sx/hs-runtime.sx b/shared/static/wasm/sx/hs-runtime.sx index a356d826..5c7043a6 100644 --- a/shared/static/wasm/sx/hs-runtime.sx +++ b/shared/static/wasm/sx/hs-runtime.sx @@ -314,6 +314,23 @@ (let ((str-val (if (list? value) (join "" (map (fn (x) (str x)) value)) value))) (do (dom-set-inner-html target str-val) (hs-boot-subtree! target))))) + (define + hs-set-element! + (fn + (target value) + (let ((parent (dom-parent target))) + (when parent + (let ((tmp (dom-create-element "div")) + (str-val (if (list? value) (join "" (map (fn (x) (str x)) value)) value))) + (do + (dom-set-inner-html tmp str-val) + (let ((children (host-get tmp "children"))) + (if (> (len children) 0) + (let ((new-el (first children))) + (do + (host-call parent "replaceChild" new-el target) + (hs-boot-subtree! new-el))) + (hs-set-inner-html! target str-val))))))))) (define hs-put! (fn diff --git a/spec/tests/test-hyperscript-behavioral.sx b/spec/tests/test-hyperscript-behavioral.sx index 8315a315..5b7945d8 100644 --- a/spec/tests/test-hyperscript-behavioral.sx +++ b/spec/tests/test-hyperscript-behavioral.sx @@ -3927,8 +3927,7 @@ (dom-append (dom-body) _el-button) (hs-activate! _el-button) (dom-dispatch _el-button "click" nil) - (assert= (dom-text-content (dom-query-by-id "target")) "new") - )) + (assert= (dom-text-content (dom-query-by-id "target")) "new"))) (deftest "set #id replaces element with HTML string" (hs-cleanup!) (let ((_el-target (dom-create-element "div")) (_el-button (dom-create-element "button")))