HS take command: class/attr with+giving, attr removal from scope, giving keyword

- tokenizer: add 'giving' as keyword so parse-take-cmd can detect it.
- parser.sx parse-take-cmd: loop over 'with <class>' / 'giving <class>' /
  'from <sel>' / 'for <tgt>' clauses in any order for both the class and
  attribute cases. Emits uniform (take! kind name from-sel for-tgt
  attr-val with-val) 7-slot AST.
- compiler emit-take: pass with-cls for the class case through to runtime.
- runtime hs-take!: with a class 'with' replacement, toggle both classes
  across scope + target. For attribute take, always strip the attr from
  the scope 'others' (setting to with-val if given, otherwise removing).
- generator pw-body: translate evaluate(() => document.querySelector(s).
  click()) and .dispatchEvent(new Event('name', …)) into dom-dispatch ops
  so bubbling-click assertions in 'parent takes…' tests work.
- generator toHaveClass: strip JS regex word-boundaries (\\b) from the
  expected class name.
- shared/static/wasm/sx/dom.sx: dom-child-list / dom-child-nodes mirror
  the dom-query-all SX-list passthrough — childNodes arrives pre-SXified.

Net: take 6→15 (100%), remove 16→17, fetch 11→15.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-23 16:51:17 +00:00
parent 3528cef35a
commit 601fdc1c34
11 changed files with 356 additions and 143 deletions

View File

@@ -1648,48 +1648,94 @@
((collect (fn () (when (= (tp-type) "class") (let ((v (tp-val))) (adv!) (set! classes (append classes (list v))) (collect))))))
(collect)
(let
((from-sel (if (match-kw "from") (parse-expr) nil)))
(let
((for-tgt (if (match-kw "for") (parse-expr) nil)))
(if
(= (len classes) 1)
(list
(quote take!)
"class"
(first classes)
from-sel
for-tgt)
(cons
(quote do)
(map
(fn
(cls)
(list
(quote take!)
"class"
cls
from-sel
for-tgt))
classes))))))))
((with-cls nil) (from-sel nil) (for-tgt nil))
(define
parse-cls-clauses
(fn
()
(cond
((and (nil? with-cls) (match-kw "with") (= (tp-type) "class"))
(do
(set! with-cls (tp-val))
(adv!)
(parse-cls-clauses)))
((and (nil? with-cls) (match-kw "giving") (= (tp-type) "class"))
(do
(set! with-cls (tp-val))
(adv!)
(parse-cls-clauses)))
((and (nil? from-sel) (match-kw "from"))
(do
(set! from-sel (parse-expr))
(parse-cls-clauses)))
((and (nil? for-tgt) (match-kw "for"))
(do
(set! for-tgt (parse-expr))
(parse-cls-clauses)))
(true nil))))
(parse-cls-clauses)
(if
(= (len classes) 1)
(list
(quote take!)
"class"
(first classes)
from-sel
for-tgt
nil
with-cls)
(cons
(quote do)
(map
(fn
(cls)
(list
(quote take!)
"class"
cls
from-sel
for-tgt
nil
with-cls))
classes)))))))
((= (tp-type) "attr")
(let
((attr-name (get (adv!) "value")))
(let
((attr-val (if (and (= (tp-type) "op") (= (tp-val) "=")) (do (adv!) (get (adv!) "value")) nil)))
(let
((with-val (if (match-kw "with") (parse-expr) nil)))
(let
((from-sel (if (match-kw "from") (parse-expr) nil)))
(let
((for-tgt (if (match-kw "for") (parse-expr) nil)))
(list
(quote take!)
"attr"
attr-name
from-sel
for-tgt
attr-val
with-val)))))))
((with-val nil) (from-sel nil) (for-tgt nil))
(define
parse-attr-clauses
(fn
()
(cond
((and (nil? with-val) (match-kw "with"))
(do
(set! with-val (parse-expr))
(parse-attr-clauses)))
((and (nil? with-val) (match-kw "giving"))
(do
(set! with-val (parse-expr))
(parse-attr-clauses)))
((and (nil? from-sel) (match-kw "from"))
(do
(set! from-sel (parse-expr))
(parse-attr-clauses)))
((and (nil? for-tgt) (match-kw "for"))
(do
(set! for-tgt (parse-expr))
(parse-attr-clauses)))
(true nil))))
(parse-attr-clauses)
(list
(quote take!)
"attr"
attr-name
from-sel
for-tgt
attr-val
with-val)))))
(true nil))))
(define
parse-pick-cmd